synchronized 是我们的同步的一种选择,在我们的印象中被synchronized锁住的代码块,线程之间是互斥的。 其实不然! synchronized锁住的是一个对象,如果锁住的这个对象,在多个线程中相同,那么这些线程访问synchronized修饰的代码块时,总是互斥的。 但是,如果锁住的这个对象,在多个线程中是不同的,那么这些线程访问synchronized修饰的代码块,是不会互斥的! 下面演示一下错误加锁的的情况:
class Lock {
public Lock(String id) {
this.id = id;
}
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
错误加锁,不互斥
public class MySynchronzedTest {
public static void main(String[] args) throws InterruptedException {
Lock lock = new Lock("a");
Lock lock1 = new Lock("a");
new Thread(() ->{
try {
m1(lock);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
m1(lock1);
Thread.sleep(10000);
}
/**
* 加锁
*/
public static void m1(Lock t) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "在排队" + new Date());
synchronized (t) {
System.out.println(Thread.currentThread().getName() + "获取到锁" + new Date());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "结束了" + new Date());
}
}
}
main在排队Wed Aug 09 14:29:05 CST 2023
Thread-0在排队Wed Aug 09 14:29:05 CST 2023
main获取到锁Wed Aug 09 14:29:05 CST 2023
Thread-0获取到锁Wed Aug 09 14:29:05 CST 2023
Thread-0结束了Wed Aug 09 14:29:07 CST 2023
main结束了Wed Aug 09 14:29:07 CST 2023
可以看到在main线程未释放锁的时候,Thread-0也进来了,虽然lock和lock1的属性值相同,但他们都是new出来的的所以是不同的对象。
可以将锁对象换成Lock.class,在多个线程中相同,这样就可以实现互斥
public class MySynchronzedTest {
public static void main(String[] args) throws InterruptedException {
Lock lock = new Lock("a");
Lock lock1 = new Lock("a");
new Thread(() ->{
try {
m1(lock.getClass());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
m1(lock1.getClass());
Thread.sleep(10000);
}
/**
* 加锁
*/
public static void m1(Class clazz) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "在排队" + new Date());
synchronized (clazz) {
System.out.println(Thread.currentThread().getName() + "获取到锁" + new Date());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "结束了" + new Date());
}
}
}
Thread-0在排队Wed Aug 09 14:40:00 CST 2023
main在排队Wed Aug 09 14:40:00 CST 2023
Thread-0获取到锁Wed Aug 09 14:40:00 CST 2023
Thread-0结束了Wed Aug 09 14:40:02 CST 2023
main获取到锁Wed Aug 09 14:40:02 CST 2023
main结束了Wed Aug 09 14:40:04 CST 2023