Java多线程编程笔记
Java多线程编程核心技术
链接:https://pan.baidu.com/s/1waW7B9PTmkNMS-qkh6LNKg 提取码:cm4i
synchronized
synchronized同步方法
- 方法内的变量为线程安全的(因为局部变量在栈中,又因为栈是线程私有的,线程安全)
- 实例变量非线程安全(实例对象存在堆中,堆是线程共享区域,非线程安全)
- 多个对象会有多个锁
- synchronized锁可重入性(持有锁A后,可调用其它需要持有锁A的方法,若不可重入则会死锁)
- 出现异常时,锁会自动释放
- 同步不能被子类继承
synchronized同步代码块
- synchronized方法的弊端(当锁住的方法执行时间特别长时,等待该锁的其他线程就需要等待较长时间,推荐使用同步代码块锁关键代码,也就是需要同步的某一块代码)
- 使用String对象做监视器时,应着重注意(String对象存在于常量池或堆中)
- 锁对象的改变(对于锁对象而言,只要这个对象没变,即使修改了它的属性,结果还是同步的。例如对于一个student对象而言,当其作为锁对象存在时,修改它的学号姓名都没有问题,结果依旧会是同步的)
- synchronized(非 this 对象 x)可得出三个结论:
- 多个线程执行synchronized(x){}代码块时是同步效果
- 其它线程执行对象 x 中的synchronized方法时是同步效果
- 其它线程执行对象 x 中的synchronized(this){}代码块时是同步效果
小结
- synchronized(class){} 的锁是类
- synchronized(this){} 的锁是本类的实例对象
- synchronized(非 this 对象 x){} 的锁是实例对象 x
- synchronized public void set() {} 的锁是本类的实例对象
- synchronized public static void set() {} 的锁是类
注意:多线程情况下,只有持有相同的锁,才能达到同步效果
生产者 / 消费者模式实现
原理都是基于wait和notify来实现的
一生产一消费:操作值
public class ValueObject {
public static String value = "";
}
生产者
public class P {
private String lock;
public P(String lock){
this.lock = lock;
}
public void setValue(){
try {
synchronized (lock){
if (!ValueObject.value.equals("")){
lock.wait();
}
String value = System.currentTimeMillis() + "_" + System.nanoTime();
ValueObject.value = value;
System.out.println("set的值是:" + value);
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
消费者
public class C {
private String lock;
public C(String lock){
this.lock = lock;
}
public void getValue(){
try {
synchronized (lock){
if (ValueObject.value.equals("")){
lock.wait();
}
String value = ValueObject.value;
System.out.println("get的值是:" + value);
ValueObject.value = "";
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
// 单个生产者消费者
public static void main(String[] args) {
String lock = "";
P p = new P(lock);
C c = new C(lock);
ThreadP threadP = new ThreadP(p);
ThreadC threadC = new ThreadC(c);
threadP.start();
threadC.start();
}
}
class ThreadC extends Thread{
private C c;
public ThreadC(C c){
this.c = c;
}
@Override
public void run() {
while (true){
c.getValue();
}
}
}