黑马程序员——Java多线程—线程互斥—synchronized
2014-09-28 10:21
155 查看
对象的锁
在Java中,所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数。
在线程第一次给对象加锁的时候,锁的计数变为1;每当这个相同的线程在此对象上再次加锁时,计数会递增,只有首先获得锁的线程才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法或代码块,计数递减;当计数为0的时候,锁被完全释放,此时别的线程就可以获得此对象的锁,进而访问共享资源。
在Java中synchronized为多线程互斥访问共享资源提供了支持。
synchronized有2种作用域:
1、实例范围:所谓实例范围是指synchronized关键字用在实例方法中。
2、类范围:所谓类范围是指synchronized关键字用在类方法中。
对于每一种作用域都有2种表现形式:
1、synchronized方法
2、synchronized代码块
实例范围+synchronized方法
当使用synchronized修饰非静态成员方法时,无需指定要获取哪个对象的锁,系统会默认获取当前对象(即this)的锁。
如果一个类有多个被synchronized修饰的非静态成员方法,只要有一个线程正在访问任意一个非静态synchronized方法,则其它线程不能再访问这个类中任何非静态的synchronized方法。但是,不同的对象实例的synchronized方法是不相干扰的;也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法。
实例范围+synchronized代码块
当使用synchronized代码块时,必须显式指定获取锁的对象,这个对象是任意的,可以是当前对象(即this),也可以是类中的成员属性等;但是必须保证当多个线程来获取该对象的锁时,得到的是同一把锁(即上面代码中的obj对多个线程来说是同一个对象),否则该代码块不能被互斥访问。
类范围+synchronized方法
static 和 synchronized 的先后顺序是任意的。
当使用synchronized修饰类方法时,无需指定要获取哪个对象的锁,系统会默认获取本类的类对象(即Test.class)的锁。
如果一个类中有多个被synchronized修饰的类方法,那么在同一时刻只能有一个线程可以获得Test.class对象的锁,也就只能有一个synchronized类方法运行。
类范围+synchronized代码块
完全类似于实例范围+synchronized代码块。
注意:
1、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
2、无论synchronized关键字加在方法上还是代码块上,它取得的锁都是对象,而不是把一段代码或函数当作锁。
3、实现互斥是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的互斥控制。
如果使用synchronized控制线程互斥,则线程会在如下几种情况下释放对监视器的锁定:
1、当前线程的synchronized方法、synchronized代码块执行结束,当前线程即释放监视器。
2、当前线程在synchronized方法、synchronized代码块中遇到break、return终止了该方法、该代码块的继续执行,当前线程会释放监视器。
3、当前线程在synchronized方法、synchronized代码块中出现了未处理的Error或Exception,导致该方法、该代码块异常结束时,当前对象会释放监视器。
4、当前线程执行synchronized方法、synchronized代码块是,执行了监视器对象的wait方法,则当前线程暂停,并释放监视器。
出现如下情况不会释放监视器:
1、线程执行synchronized方法、synchronized代码块时,程序调用了Thread.sleep()、Thread.yield()方法来暂停当前线程的执行,当前线程不会释放监视器。
2、线程执行synchronized方法、synchronized代码块时,其他线程调用了该线程的suspend方法将该线程挂起,该线程不会释放监视器(我们应该尽量避免使用suspend、resume方法来控制线程)。
参考:
CSDN:
【Java线程】锁机制:synchronized、Lock、Condition
CSDN:
Java多线程编程--(3)线程互斥、同步的理解
CSDN 高爽:Java线程(二):线程同步synchronized和volatile
51CTO: Java锁机制Synchronized
在Java中,所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数。
在线程第一次给对象加锁的时候,锁的计数变为1;每当这个相同的线程在此对象上再次加锁时,计数会递增,只有首先获得锁的线程才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法或代码块,计数递减;当计数为0的时候,锁被完全释放,此时别的线程就可以获得此对象的锁,进而访问共享资源。
在Java中synchronized为多线程互斥访问共享资源提供了支持。
synchronized有2种作用域:
1、实例范围:所谓实例范围是指synchronized关键字用在实例方法中。
2、类范围:所谓类范围是指synchronized关键字用在类方法中。
对于每一种作用域都有2种表现形式:
1、synchronized方法
2、synchronized代码块
实例范围+synchronized方法
public class Test{ public synchronized void method1(){ // 需要被互斥访问的代码 } }
当使用synchronized修饰非静态成员方法时,无需指定要获取哪个对象的锁,系统会默认获取当前对象(即this)的锁。
如果一个类有多个被synchronized修饰的非静态成员方法,只要有一个线程正在访问任意一个非静态synchronized方法,则其它线程不能再访问这个类中任何非静态的synchronized方法。但是,不同的对象实例的synchronized方法是不相干扰的;也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法。
实例范围+synchronized代码块
public class Test{ public void method1(){ // 无需互斥访问的代码 synchronized(obj){ // 需要被互斥访问的代码块 } } }
当使用synchronized代码块时,必须显式指定获取锁的对象,这个对象是任意的,可以是当前对象(即this),也可以是类中的成员属性等;但是必须保证当多个线程来获取该对象的锁时,得到的是同一把锁(即上面代码中的obj对多个线程来说是同一个对象),否则该代码块不能被互斥访问。
类范围+synchronized方法
public class Test{ public static synchronized void method1(){ // 需要被互斥访问的代码 } public synchronized static void method2(){ // 需要被互斥访问的代码 } }
static 和 synchronized 的先后顺序是任意的。
当使用synchronized修饰类方法时,无需指定要获取哪个对象的锁,系统会默认获取本类的类对象(即Test.class)的锁。
如果一个类中有多个被synchronized修饰的类方法,那么在同一时刻只能有一个线程可以获得Test.class对象的锁,也就只能有一个synchronized类方法运行。
类范围+synchronized代码块
public class Test{ public static void method1(){ // 不需要被互斥访问的代码 synchronized(obj){ // 需要被互斥访问的代码 } } }
完全类似于实例范围+synchronized代码块。
注意:
1、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
2、无论synchronized关键字加在方法上还是代码块上,它取得的锁都是对象,而不是把一段代码或函数当作锁。
3、实现互斥是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的互斥控制。
如果使用synchronized控制线程互斥,则线程会在如下几种情况下释放对监视器的锁定:
1、当前线程的synchronized方法、synchronized代码块执行结束,当前线程即释放监视器。
2、当前线程在synchronized方法、synchronized代码块中遇到break、return终止了该方法、该代码块的继续执行,当前线程会释放监视器。
3、当前线程在synchronized方法、synchronized代码块中出现了未处理的Error或Exception,导致该方法、该代码块异常结束时,当前对象会释放监视器。
4、当前线程执行synchronized方法、synchronized代码块是,执行了监视器对象的wait方法,则当前线程暂停,并释放监视器。
出现如下情况不会释放监视器:
1、线程执行synchronized方法、synchronized代码块时,程序调用了Thread.sleep()、Thread.yield()方法来暂停当前线程的执行,当前线程不会释放监视器。
2、线程执行synchronized方法、synchronized代码块时,其他线程调用了该线程的suspend方法将该线程挂起,该线程不会释放监视器(我们应该尽量避免使用suspend、resume方法来控制线程)。
参考:
CSDN:
【Java线程】锁机制:synchronized、Lock、Condition
CSDN:
Java多线程编程--(3)线程互斥、同步的理解
CSDN 高爽:Java线程(二):线程同步synchronized和volatile
51CTO: Java锁机制Synchronized
相关文章推荐
- Java多线程与并发应用-(2)-线程互斥synchronized
- 【Java多线程与并发库】03 传统线程互斥技术 synchronized
- 黑马程序员-JAVA学习之多线程和synchronized关键字
- 黑马程序员-19-java基础-多线程(2)-死锁与线程间通信(synchronized与Lock的区别及各自用法)
- 黑马程序员入学篇——(7)java的多线程(续写)
- Java的多线程编程模型4--synchronized
- java 多线程(二)synchronized
- java多线程-线程池-synchronized-死锁
- java多线程设计wait、notify、notifyall、synchronized的使用机制
- Java【多线程知识总结(7)】多线程同步问题-关于synchronized代码块和synchronized方法的应用
- 黑马程序员入学篇——(6)java的多线程
- java多线程synchronized注意的地方
- 黑马程序员 java中的多线程
- 黑马程序员0831_java基础知识+多线程部分
- 黑马程序员_java多线程
- Java多线程Synchronized心得
- java多线程设计wait/notify机制 (synchronized与对象锁)
- Java 多线程编程之三:synchronized 关键字的使用
- 黑马程序员Java培训、Android培训-Java 学习过程记录_多线程
- 黑马程序员-java多线程