synchronized 使用场景
- synchronized包裹代码块:
I . synchronized(对象){}
II . synchronized(类名.class){}
III. synchronized(this){} - synchronized修饰方法:
I .public synchronized void memberMethod(){};
II.public static synchronized void staticMethod(){};
相关赘述
内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。– 查看出处
对象锁:假设类对象instance的某段代码块被synchronized(obj){}包裹,线程访问该段代码块时便会拿到obj对象的内置锁。在obj对象的内置锁释放前,其他线程仍然可以访问instance对象非同步的方法和代码块(现象一),但是:
1. 不能进入任何也以obj为锁的代码块;(现象二)
2. 当obj与instance是同一个对象时,也不能进入任何instance对象的同步方法(现象三)
由此可见,第一个线程拿到obj对象的内置锁其实就相当于给instance这个对象加上了一个用于同步的独占排他锁(可重入),我们称obj对象为对象锁。– 查看详情类锁:是相对于对象锁而抽象出来的一种独占排他锁。当线程拿到一个类A的类锁时,其他线程无法访问以类A为锁(A.class)的同步代码块,也无法进入类A的所有静态同步方法。– 查看详情
结论
无论修饰的是代码块还是方法,只要指定的锁相同就一定会引起多线程的竞争和部分线程阻塞!
判断的关键便是从形式多变的synchronized关键词中挖掘出锁。
现在假设有类A,另有Object类对象obj。得下表:
synchronized形式(均写在在类A中) | 锁 | 锁类型 |
---|---|---|
synchronized(obj){} | obj | 对象锁 |
synchronized(A.class){} | A.class | 类锁 |
synchronized(this){} | 当前类对象 | 对象锁 |
synchronized void memberMethod(){} | 当前类对象 | 对象锁 |
static synchronized void staticMethod(){} | 当前类 | 类锁 |
场景分析
场景一:synchronized包裹代码块
场景二:synchronized修饰成员方法
其他(待补充)
1.两种场景的区别
2.使用synchronized关键字的缺陷
3.如有问题或错误,请评论告知
SynchronizedVerify类代码
public class SynchronizedVerify {
/**-------------------------------------包裹代码块------------------------------**/
Object objA = new Object();
Object objB = new Object();
public void blockNormal(){ track("blockNormal");}
public void blockStyle(){
synchronized (objA) { track("blockStyle"); }
}
/**相同场景下对比**/
public void blockContrast( ){
synchronized (objA) { track("blockContrast");}
}
public void blockDiffObj(){
synchronized (objB) { track("blockDiffObj");}
}
public void blockOneself(){
synchronized (this) { track("blockOneself");}
}
public void blockClass(){
synchronized (SynchronizedVerify.class) { track("blockClass");}
}
/**-------------------------------------修饰方法------------------------------**/
public void methodNormal(){ track("methodNormal");}
public synchronized void methodStyle(){ track("methodStyle");}
public synchronized void methodContrast(){ track("methodContrast");}/**相同场景下对比**/
public static void methodStaticNormal(){ track("methodStaticNormal");}
public synchronized static void methodStatic(){ track("methodStatic");}
public synchronized static void methodStaticContrast(){ track("methodStaticContrast");}
/**循环输出一段内容**/
private static void track(String callerName){
for(int i = 0;i < 3 ;i++){
System.out.println(
callerName+":"+i+"\t|"+
Thread.currentThread().getName());
Thread.yield();
}
}
}