最近在学习JUC这一块知识点,碰到一个问题就是为什么Synchronize在同步代码块的时候要传入一个this
这个锁机制到底是个什么意思,通过我的实验,初步理解如下:
首先第一点:在Java中万物皆对象,任何对象都可以作为锁。
所以不管是xxx.class
还是传入一个this
都可以作为一把锁(其实这两个也都是实例对象,然后就有了类锁和对象锁)
贴一段代码,这是一段线程不安全的代码
public static void main(String[] args) {
List<String> list = new ArrayList();
for (int i = 0; i < 3; i++)
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}).start();
}
如果对这段代码块加Synchronized
//为每一个线程分配一个锁
public static void main(String[] args) {
List<String> list = new ArrayList();
for (int i = 0; i < 3; i++)
new Thread(() -> {
Object lack = new Object();
synchronized (lack) {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}
}).start();
}
//使用同一个锁
public static void main(String[] args) {
List<String> list = new ArrayList();
Object lack = new Object();
for (int i = 0; i < 3; i++)
new Thread(() -> {
synchronized (lack) {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}
}).start();
}
当为每一个线程分配一个锁的时候,则该代码还是不安全的
如果三个线程共用一个锁的话,则实现了线程安全
结论:
Java底层为每一个对象(锁对象)都设置了记录访问线程的功能,当线程进入该锁对象锁定的代码块时,该锁对象则记录下当前线程(这个很容易实现)。
当其他的线程再来访问该锁对象的时候,该锁对象中已经记录一个线程,所以其他对象无法访问代码块,处于等待。
当当前线程执行完代码,锁对象则将记录中的线程清除,其他线程则有机会拿到该锁对象。