Java关于Synchronized关键字在不同位置使用的理解

Java中的Synchronized关键字

可以用来修饰同步方法:

像这样synchronized void f() {/*body*/}

也可以修饰同步语句块:

像这样synchronized(object){/*body*/}。

其中修饰同步方法还可以分为修饰static方法和实例方法。

其中修饰同步语句块还可以分为修饰instance变量,Object Reference对象引用,class 字面常量。

当synchronized作用在方法上时,锁住的便是对象实例(this);

所以synchronized void f() {/*body*/}和 void f(synchronized(this){/*body*/})是等价的。

当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;

当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。

在HotSpot JVM实现中,锁有个专门的名字:对象监视器。

synchronized(class)

synchronized(this)

->线程各自获取monitor,不会有等待.

线程分别获取class和this,不会造成等待的例子:

package com.hyy.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SyncTest02 implements Runnable {

	private static boolean flag = true;

	private void testSync1() {
		synchronized (this) {
			for (int i = 0; i < 100; i++) {
				System.out.println("testSyncObject: " + i);
			}
		}
	}

	private void testSync2() {
		synchronized (SyncTest02.class) {
			for (int i = 0; i < 100; i++) {
				System.out.println("testSyncClass:" + i);
			}
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub

		if (flag) {
			flag = false;
			testSync1();
		} else {
			flag = true;
			testSync2();
		}

	}

	public static void main(String[] args) {
		ExecutorService exec = Executors.newFixedThreadPool(2);
		SyncTest02 sy1 = new SyncTest02();
		SyncTest02 sy2 = new SyncTest02();

		exec.execute(sy1);
		exec.execute(sy2);
		exec.shutdown();
	}

}

synchronized(this)

synchronized(this)

->如果不同线程监视同一个实例对象,就会等待,如果不同的实例,不会等待.

不同线程监视同一个实例对象的例子:

package com.hyy.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SyncTest {

	public static void main(String[] args) {
		ExecutorService es = Executors.newFixedThreadPool(2);
		MyCount mc = new MyCount();
		MyThread mt1 = new MyThread(mc, "thread 1");
		MyThread mt2 = new MyThread(mc, "thread 2");
		es.execute(mt1);
		es.execute(mt2);
		es.shutdown();
	}

}

class MyThread extends Thread {

	MyCount count;
	String threadName;

	public MyThread(MyCount count, String threadName) {
		// TODO Auto-generated constructor stub
		this.count = count;
		this.threadName = threadName;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			count.addOne(threadName);

			try {
				sleep(100L);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

class MyCount {
	int i;

	public void addOne(String threadName) {
		synchronized (this) {
			i++;
			System.out.println(threadName + ":" + i);
		}

	}
}

输出为

thread 1:1
thread 2:2
thread 1:3
thread 2:4
thread 2:5
thread 1:6
thread 2:7
thread 1:8
thread 1:9
thread 2:10
thread 1:11
thread 2:12
thread 2:13
thread 1:14
thread 1:15
thread 2:16
thread 1:17
thread 2:18
thread 1:19
thread 2:20

从输出上看,线程间出现了等待

不同线程监视不同实例对象的例子:

package com.hyy.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SyncTest {

	public static void main(String[] args) {
		ExecutorService es = Executors.newFixedThreadPool(2);
		MyCount mc = new MyCount("countONE");
		MyCount mc2 = new MyCount("countTWO");
		MyThread mt1 = new MyThread(mc, "thread 1");
		MyThread mt2 = new MyThread(mc2, "thread 2");
		es.execute(mt1);
		es.execute(mt2);
		es.shutdown();
	}

}

class MyThread extends Thread {

	MyCount count;
	String threadName;

	public MyThread(MyCount count, String threadName) {
		// TODO Auto-generated constructor stub
		this.count = count;
		this.threadName = threadName;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			count.addOne(threadName);

			try {
				sleep(100L);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

class MyCount {

	int i;
	String countName;

	public MyCount(String countName) {
		// TODO Auto-generated constructor stub
		this.countName = countName;
	}

	public void addOne(String threadName) {
		synchronized (this) {
			i++;
			System.out.println(threadName +"&&"+countName+ ":" + i);
		}

	}
}

输出为

thread 2&&countTWO:1
thread 1&&countONE:1
thread 2&&countTWO:2
thread 1&&countONE:2
thread 2&&countTWO:3
thread 1&&countONE:3
thread 2&&countTWO:4
thread 1&&countONE:4
thread 1&&countONE:5
thread 2&&countTWO:5
thread 2&&countTWO:6
thread 1&&countONE:6
thread 2&&countTWO:7
thread 1&&countONE:7
thread 1&&countONE:8
thread 2&&countTWO:8
thread 2&&countTWO:9
thread 1&&countONE:9
thread 1&&countONE:10
thread 2&&countTWO:10

从输出上看,线程间没有发上等待。

synchronized(class)

synchronized(class)

->如果不同线程监视同一个实例或者不同的实例对象,都会等待.

不同线程监视不同实例对象的例子:

package com.hyy.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SyncTest02 implements Runnable {

	private static boolean flag = true;

	private void testSync1() {
		synchronized (SyncTest02.class) {
			for (int i = 0; i < 100; i++) {
				System.out.println("testSyncObject: " + i);
			}
		}
	}

	private void testSync2() {
		synchronized (SyncTest02.class) {
			for (int i = 0; i < 100; i++) {
				System.out.println("testSyncClass:" + i);

			}
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub

		if (flag) {
			flag = false;
			testSync1();
		} else {
			flag = true;
			testSync2();
		}

	}

	public static void main(String[] args) {
		ExecutorService exec = Executors.newFixedThreadPool(2);
		SyncTest02 sy1 = new SyncTest02();
		SyncTest02 sy2 = new SyncTest02();

		exec.execute(sy1);
		exec.execute(sy2);
		exec.shutdown();
	}

}
时间: 2024-11-10 10:40:58

Java关于Synchronized关键字在不同位置使用的理解的相关文章

从分布式锁角度理解Java的synchronized关键字

分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备事务能力,在并发状态下可能出现对单个数据同时读写.客户端A,B是数据系统D提供的客户端,能够对其读写. 几个关键角色已经登场,D是一个不提供事务行为的数据系统,其存放的数据可被读写,在单客户端条件下可以保证数据的可靠,但是在两个客户端可能并发请求时就变得不可靠,A写的数据可能被B覆盖,B读的数据可能

Java基础-synchronized关键字的用法(转载)

原文地址:http://blog.csdn.net/cq361106306/article/details/38736551 synchronized--同步 顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 当synchronized修饰?this或者非静态方法或者是一个实例的时候,所同步的锁是加在this或者实例对象引用上面的.比如a,b同为Main类的实例化对象,a调用被同步的方法,和b调用被同步的方法,没有形成互斥.但是不同线程的a对象调用被同步的方法就被互斥了.

Java中synchronized关键字理解

好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式. (1)对于普通同步方法,锁是当前实例对象. (2)对于静态同步方法,锁是当前类的Class对象. (3)对于同步方法块,锁是synchronized括号里配置的对象. 一.普通同步方法 使用synchronized关键字修饰一个普通方法,锁住的是当前实例的对象.当synchronized锁住该对

Java多线程synchronized关键字

synchronized关键字代表着同步的意思,在Java中被synchronized修饰的有三种情况 1.同步代码块 //锁为objsynchronized(obj){ while(true){ if(product > 0){ System.out.println(Thread.currentThread().getName()+"消费:"+product--); } } } 2.同步函数 //锁为thispublic synchronized void consume()

java中synchronized关键字的用法

在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法. java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A

尝试在C++里实现 Java 的 synchronized 关键字

话说Java里有个很强大的关键字叫synchronized,可以方便的实现线程同步.今天异想天开,尝试在C++里模拟一个类似的. 最近在学习C++的STL,看见智能指针这章节时,无不感叹利用语言的丰富特征,来各种实现各种巧妙的构思.最经典的莫过于使用栈对象构造/析构函数,来维护局部资源的初始化和释放.照着这个巧妙的方法,依样画葫芦自己也来写一个,来实现局部代码线程同步. Java里的synchronized有两种形式,一种是基于函数的,另种则是语块的.前者受C++的语法所限,估计是没法实现了,所

Java中synchronized关键字实现同步(二)

我们知道synchronized有两种:同步方法(synchronized method)和同步语句块(synchronized block).那么这两种有什么区别以及优缺点呢? SynchronizedMethod: 优点:代码简单清晰:易于维护 缺点:同步粒度过大,不利于并发:不够灵活,默认用本对象或者本类锁同步 Synchronizedblock  : 优点:灵活,可以使用任意对象锁:同步粒度小,并发度更高 缺点:代码更复杂,不易于维护 对比: Synchronized method: 默

Java基础-synchronized关键字的用法

顾名思义是用于同步互斥的作用的. 这里精简的记一下它的使用方法以及意义: 1. 当synchronized修饰 this或者非静态方法或者是一个实例的时候,所同步的锁是加在this或者实例对象引用上面的.比如a,b同为Main类的实例化对象,a调用被同步的方法,和b调用被同步的方法,没有形成互斥.但是不同线程的a对象调用被同步的方法就被互斥了. public synchronized void method(){   //-.   }   public void method()   {   s

java synchronized关键字

Java中synchronized关键字和对象的内置锁结合使用,用来保护代码块在并发环境下的线程安全,可以使被保护的代码块操作原子性. synchronized关键字可以用于修饰方法来保护方法内的全部代码块,可以用synchronized(对象1) 的方式保护指定代码块.(这里说一下:很多书中都说synchronized可以给对象加锁,我实在不愿意这么说,这样让我概念混淆...因为,对象内置锁是本来就存在的,不是谁加给它的,"synchronized(对象1)"我更愿意解释成:执行到此