在写这篇文章之前我看过一些关于多线程同步的文章,从他们的文章中总结了很多精华,也发现一些不足。很多文章都是从以下四个方面来分析的。
1、synchronized修饰一个非静态函数,例如synchronized method()
2、synchronized修饰一个静态函数,例如static synchronized method()
3、synchronized修饰一个对象,例如synchronized(obj){}
4、synchronized修饰一个类,例如synchronized(Object.class){}
本文我想从一个新的角度来分析多线程同步:对象锁、类锁。
对象锁:
问题1:一个线程什么时候获得某个对象的对象锁,又在什么时候释放该对象锁呢?
当一个线程执行obj.synchronized method(),或者执行synchronized(obj){}代码块时,该线程获得对象obj的对象锁。当该同步方法或者该代码块执行完毕时,该线程释放obj的对象锁。
结论1:线程1获得对象obj的对象锁之后,其他的线程若想获得该对象锁,需要等到线程1释放该对象锁
结论2:线程1执行obj.synchronized method()前,要先获得obj的对象锁
结论3:线程1执行synchronized(obj){}代码块前,要先获得obj的对象锁
类锁:
问题1:一个线程什么时候获得某个类的类锁?又在什么时候释放该类锁呢?
当一个线程执行H.static synchronized method(),或者执行synchronized(H.class){}代码块时,该线程获得该类H的类锁。当该静态同步方法或者同步代码块执行完毕时,该线程释放该H的类锁。
结论1:线程1获得类H的类锁之后,其他线程若想获得该类锁,需要等到线程1释放该类锁。
结论2:线程1执行H.static synchronized method()前,要先获得类H的类锁。
结论3:线程1执行synchronized(H.class){}代码块前,要先获得类H的类锁。
类锁和同步锁是相互不影响的
1、若类H的某个对象h1的对象锁是空闲的,当一个线程获得了类H的类锁之后,h1的对象锁依然是空闲的
2、若类H的类锁是空闲的,当一个线程获得类H的某个对象h1的对象锁之后,H的类锁依然是空闲的
普通方法和同步方法或同步代码块的区别
同步方法或者同步代码块需要执行它们的线程获得相应的锁(类锁或者对象锁)之后才能执行,否则会阻塞在该处直到获得相应的锁。而普通方法,一旦调用就会立即执行,与当前线程是否获得同步锁没有关系。
如果某段代码f需要获得类A的对象a1的对象锁才能执行,某段代码g需要获得类A的对象a2的对象锁才能知行,问当线程1在执行f时,同时执行的线程2的g是否会阻塞?
答案是不会阻塞。因为线程1在执行f时只获得了a1的对象锁,a2的对象锁依然是空闲的,所以线程2在执行g时可以立马获得a2的对象锁