JUC进阶
JUC进阶
wait和sleep的区别
-
-
sleep不会释放锁,它也不需要占用锁,wait会释放锁但调用它的前提是当前线程占有锁
-
wait必须在同步代码块中
Lock锁
public class LockTest {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 40; i++) ticket.sale();
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) ticket.sale();
}, "BB").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) ticket.sale();
}, "CC").start();
}
}
class Ticket {
private int number = 40;
//定义可重入锁
Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + number--);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
Lock和Synchronized的区别
-
Synchronized内置的Java关键字,Lock是一个Java类
-
Synchronized无法判断获取锁的状态 ,Lock可以判断是否获取到了锁
-
Synchronized会自动释放锁,Lock锁必须要手动释放,如果不释放锁,死锁
-
Synchronized可重入锁,不可以中断的,非公平,Lock,可重入锁,可以判断锁,非公平和公平可以自己设置
-
Synchronized适合锁少量的代码同步问题,Lock适合锁大量的同步代码
生产者消费者(虚假唤醒)
老版synchronized
public class WakeThread {
public static void main(String[] args) {
Date date = new Date();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"AA").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"BB").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"CC").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"DD").start();
}
}
class Date {
private int number = 0;
public synchronized void increment() throws InterruptedException {
if(number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>" + number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "=>" + number);
this.notifyAll();
}
}
这种情况出现虚假唤醒状态,防止虚假唤醒
class Date {
private int number = 0;
public synchronized void increment() throws InterruptedException {
while (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>" + number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
while (number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "=>" + number);
this.notifyAll();
}
}
新版JUC
public class LockPC {
public static void main(String[] args) {
Date1 date1 = new Date1();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date1.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"AA").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date1.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"BB").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date1.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"CC").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
date1.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"DD").start();
}
}
class Date1 {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increment() throws InterruptedException {
lock.lock();
try {
while (number != 0) {
//等待
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>" + number);
//通知其它线程
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {