包括内容
同步方法块
同步方法
同步静态方法
示例代码
/**
* A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
* B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
* C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
*/
public class Synchronized1 {
private class Lock1 {}
private Lock1 lock = new Lock1();
/**
* 同步方法块
* 调用:obj.synchronizeFun()
* 锁的对象是obj.lock
*/
public void synchronizeCode(){
synchronized(lock){
//逻辑
}
}
/**
* 同步方法
* 调用:obj.synchronizeFun()
* 锁的对象是obj这个对象
* 说明:synchronizeFun1 和 synchronizeFun2 功能类似
*/
public synchronized void synchronizeFun1(){
//逻辑
}
public void synchronizeFun2(){
synchronized(this){
//逻辑
}
}
/**
* 同步静态方法
* 调用:Synchronize1.synchronizeStaticFun
* 锁的是所有对象
*/
public static synchronized void synchronizeStaticFun(){
}
}
总结:搞清楚锁的对象是什么
A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制
嵌套synchronized
嵌套可能导致死锁。
/**
* 测试死锁
* 1. synchronized(lock) 只锁了lock一个对象
* 2. 可以在synchronized方法块中继续同步
* synchronized (lock1) {
* synchronized (lock2) {}
* }
* 3.如示例:
* - 线程和main 分别锁了 t1,t2
* - 1s后 线程需要 t2, main 需要 t1, 彼此并没有把获取的对象释放,就要彼此的资源,导致了死锁
* 4.死锁原因:
* 一次没能获取完所需要同步的资源,再次获取是,发现资源被人占用,且占用资源的人,还需要你以及上锁的东西。
* 5. 无法使用interrupt对synchronized对资源的等待,也没法打断ReentrantLock.lock的等待
* - 可以使用interrupt对ReentrantLock.lockInterruptibly对资源的等待,见TestThreadLock3
*/
public class TestThreadLock2 implements Runnable{
private static Logger log = Logger.getLogger(TestThreadLock2.class);
private Object t1 = null;
private Object t2 = null;
public TestThreadLock2(Object t1,Object t2){
this.t2 = t2;
this.t1 = t1;
}
public static void main(String[] args) throws Exception {
Object t1 = new Object();
Object t2 = new Object();
Thread th1 = new Thread(new TestThreadLock2(t1,t2));
Thread th2 = new Thread(new TestThreadLock2(t2,t1));
th1.start();
th2.start();
char c = (char) System.in.read();
log.info("input : " + c);
if(c == 'y'){
th1.interrupt();
}
}
public void run() {
try {
synchronized (t1) {
log.info("get t1 monitor ...");
Thread.sleep(1000l * 1);
synchronized (t2) {
Thread.sleep(1000l * 3);
}
}
log.info("release t1 monitor ...");
} catch (Exception e) {
e.printStackTrace();
}
}
}