一、同步
1.1、为什么需要同步
同步是在多线程访问共享资源的情况下发生的,比如有A、B两个线程同时访问共享资源C, 并且都需要对C进行操作。这时如果没有同步机制,将导致一系列的问题。
1.2、同步的方式
java中同步方式包括以下几种方式:
1.2.1 synchronized关键字
synchronized是JVM提供的一个便捷的同步方式。每个对象都自动含有单一的锁,JVM会负责跟踪每个 对象加锁的情况。当一个对象没有加锁时,可以调用该对象的synchronized方法或者synchronized代码 块。
当C对象被A线程加锁,A线程可以访问C对象的其他方法,B线程只能等待C的锁释放后才能访问 C的synchronized方法或synchronized代码块。但是B线程能访问C的非synchronized代码块。
synchronized保证线程A退出C对象的方法时,B线程看到C对象的最新状态。
1.2.2 volatile关键字
volatile 修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。因此A线程修改被volatile修饰的变量时,B线程能够及时感应。一般用volatile修饰控制状态,比如stop、running等。
1.2.3 wait、notify机制
wait、notify必须配合synchronized关键字使用。
public class MyThread implements Runnable {
private String name;
private Object prev;
private Object self;
private MyThread(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
count--;
System.out.println(name +" release lock "+ self);
self.notify();
}
try {
System.out.println(name +" wait lock "+prev);
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThread pa = new MyThread("A", c, a);
MyThread pb = new MyThread("B", a, b);
MyThread pc = new MyThread("C", b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start();
}
}
wait、notify常用限制线程的执行顺序。wait会释放获取的C对象锁,等其他线程调用了C 对象的notify方法后,JVM会选择一个等待C对象锁的线程继续执行。
二、Thread.sleep()
Thread.sleep与wait的区别在于,sleep不会释放对象锁。
三、ThreadLocal
ThreadLocal目的是线程隔离,每个线程有自己的对象副本。而不是共享对象。
本文介绍了Java中多线程同步的重要性和不同实现方式,包括synchronized关键字、volatile关键字及wait、notify机制,并对比了Thread.sleep()与wait()的区别,最后讲解了ThreadLocal的用途。

被折叠的 条评论
为什么被折叠?



