java中synchronized的使用

synchronized是Java中的关键字,是一种同步锁。

synchronized分对象锁和类的锁两种。

(一)通常synchronized 方法和synchronized(this){}都是属于对象锁(或者实例锁)。
每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

对象锁synchronized对于同一个实例有效。举例如下:
public class C implements Runnable {
	   private static int count;

	   public C() {
	      count = 0;
	   }

	   public  void run() {
	      synchronized(this) {
	         for (int i = 0; i < 5; i++) {
	            try {
	               System.out.println(Thread.currentThread().getName() + ":" + (count++));
	               Thread.yield();
	            } catch (Exception e) {
	               e.printStackTrace();
	            }
	         }
	      }
	   }

	   public int getCount() {
	      return count;
	   }
	   public static void main(String[] args) {
		   // C syncThread = new C();
		   Thread thread1 = new Thread(new C(), "SyncThread1");   
		   Thread thread2 = new Thread(new C(), "SyncThread2");
		   thread1.start();
		   thread2.start();
	}
}

输出结果:
SyncThread1:0
SyncThread2:1
SyncThread1:2
SyncThread2:3
SyncThread1:4
SyncThread2:5
SyncThread1:6
SyncThread2:7
SyncThread1:8
SyncThread2:9

两个线程是同时执行的,并没有synchronized的效果。因为两个线程执行的任务实例是不同的,都是重新new C()

如果修改上面代码中的main函数部分,修改如下:

public static void main(String[] args) {
		   C syncThread = new C();
		   Thread thread1 = new Thread(syncThread, "SyncThread1");// 
		   Thread thread2 = new Thread(syncThread, "SyncThread2");
		   thread1.start();
		   thread2.start();
	   }

输出结果:
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
SyncThread2:5
SyncThread2:6
SyncThread2:7
SyncThread2:8
SyncThread2:9

这时synchronized起作用了,线程SyncThread1执行完毕释放锁后,SyncThread2才开始执行,因为线程任务的实例是同一个syncThread 

那么问题来了,要是我想不同的任务实例也达到synchronized的效果应该怎么办?这时候就需要用到类的锁。

(二)类锁:举例如下(还是刚才上面的例子):

public class C implements Runnable {
	   private static int count;

	   public C() {
	      count = 0;
	   }

	   public  void run() {
	      synchronized(C.class) {  //把this改成C.class变成类的锁
	         for (int i = 0; i < 5; i++) {
	            try {
	               System.out.println(Thread.currentThread().getName() + ":" + (count++));
	               Thread.yield();
	            } catch (Exception e) {
	               e.printStackTrace();
	            }
	         }
	      }
	   }

	   public int getCount() {
	      return count;
	   }
	   public static void main(String[] args) {
		   Thread thread1 = new Thread(new C(), "SyncThread1");
		   Thread thread2 = new Thread(new C(), "SyncThread2");
		   thread1.start();
		   thread2.start();
	   }
}

输出结果:
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
SyncThread2:5
SyncThread2:6
SyncThread2:7
SyncThread2:8
SyncThread2:9

这时候就达到了目的,用到的就是类的锁,即使不同的任务实例也可以实现同步功能。

以上代码只作示例说明。

posted on 2017-09-17 14:48  天生一对  阅读(148)  评论(0编辑  收藏  举报

导航