线程同步的两种手段:加锁,死锁
加锁演示:
Lock lock=new ReentrantLock();
Lock.lock();
Lock lock = new ReentrantLock(); 相比较直接用锁 可读性比较高,无需考虑异常之后的无法解锁
需要线程同步的代码:synchornized(lock){
}
object obj=new object();
synchornized(obj){ 为obj加一把锁;判断这个线程是否被其他线程占用
}
public static void main(String[] args) throws InterruptedException { List<String> list = new ArrayList<>(); Runnable r1 = new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(5); synchronized (list){ list.add("hello"); } } catch (InterruptedException e) { e.printStackTrace(); } } } }; Runnable r2 = new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(5); synchronized (list){ list.add("world"); } } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread1 = new Thread(r1); Thread thread2 = new Thread(r2); thread1.start(); thread2.start(); Thread.sleep(600); System.out.println(list); } }
死锁:在等待一个永远也不会解开的锁
单锁死锁:一线程锁上了,但是可能因为异常、忘了...,这把锁没解开 其他线程一直在等待这把锁
两锁思索:a占用了A锁。等待B锁
b占用了B锁,等待A锁
public class KuaiZiLockPractice {
public static void main(String[] args) {
Lock aLock = new ReentrantLock();
Lock bLock = new ReentrantLock();
Runnable xiaoming = new Runnable() {
@Override
public void run() {
try {
aLock.lock();
Thread.sleep(500);
bLock.lock();
Thread.sleep(500);
System.out.println("小明开始吃饭...........");
bLock.unlock();
aLock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable xiaohong = new Runnable() {
@Override
public void run() {
try {
bLock.lock();
Thread.sleep(500);
aLock.lock();
Thread.sleep(500);
System.out.println("小红开始吃饭了...........");
aLock.unlock();
bLock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t1 = new Thread(xiaoming);
Thread t2 = new Thread(xiaohong);
t1.start();
t2.start();
}
}
经典问题-消费者和生产者
生产者需等待:容器中可以放入的信号
消费者需等待:已经生产了产品的信号
在Java中等待分为两种:
限时等待,,无限等待
在等待到信号后,立即进入cpu资源抢占中。争抢结束后,会产生锁得占用,所以在没有争抢到锁的线程中会从等待状态切换个阻塞状态
等锁时会进入阻塞状态
需要使用以下两个方法:notify wait
public class HomeWork { public static void main(String[] args) throws InterruptedException { Object obj = new Object(); Runnable watiRun = new Runnable() { @Override public void run() { synchronized (obj){ try { obj.wait(); System.out.println("等到了一个包子"); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Runnable notifyRun = new Runnable() { @Override public void run() { synchronized (obj){ System.out.println("生产了一包子"); try { Thread.sleep(500); obj.notify(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; new Thread(watiRun).start(); new Thread(notifyRun).start(); Thread.sleep(6000); } }