1 synchronized 的特性
互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到 同一个对象 synchronized 就会阻塞等待. 进入 synchronized 修饰的代码块, 相当于 加锁 退出 synchronized 修饰的代码块, 相当于 解锁
可以粗略理解成, 每个对象在内存中存储的时候, 都存有一块内存表示当前的 "锁定" 状态(类似于厕 所的 "有人/无人"). 如果当前是 "无人" 状态, 那么就可以使用, 使用时需要设为 "有人" 状态. 如果当前是 "有人" 状态, 那么其他人无法使用, 只能排队
synchronized 的工作过程:
1. 获得互斥锁 2.
从主内存拷贝变量的最新副本到工作的内存
3. 执行代码
4. 将更改后的共享变量的值刷新到主内存
5. 释放互斥锁
死锁:
按照之前对于锁的设定, 第二次加锁的时候, 就会阻塞等待. 直到第一次的锁被释放, 才能获取到第 二个锁. 但是释放第一个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想干了, 也就无 法进行解锁操作. 这时候就会 死锁.、
Java 中的 synchronized 是 可重入锁, 因此没有上面的问题.
synchronized 使用示例
//1) 直接修饰普通方法: 锁的 SynchronizedDemo 对象
//2) 修饰静态方法: 锁的 SynchronizedDemo 类的对象
//3) 修饰代码块: 明确指定锁哪个对象.
//锁当前对象
//锁类对象
static class Counter {
public int count = 0;
synchronized void increase() {
count++;
}
synchronized void increase2() {
increase();
}
}
public class SynchronizedDemo {
public synchronized void methond() {
}
}
public class SynchronizedDemo {
public synchronized static void method() {
}
}
public class SynchronizedDemo {
public void method() {
synchronized (this) {
}
}
}
Java 标准库中很多都是线程不安全的. 这些类可能会涉及到多线程修改共享数据, 又没有任何加锁措施. ArrayList LinkedList HashMap TreeMap HashSet TreeSet StringBuilder 但是还有一些是线程安全的. 使用了一些锁机制来控制. Vector (不推荐使用) HashTable (不推荐使用) ConcurrentHash StringBuffer