public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
class Data {
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();
}
}
防止虚假唤醒
因为超过2个线程唤醒的时候会全部唤醒,所以if改为while判断 因为if判断只会判断一次
class Data3 {
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1;
public void printA() {
try {
lock.lock();
while (number != 1) {
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "A");
number = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() {
try {
lock.lock();
while (number != 2) {
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "B");
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC() {
try {
lock.lock();
while (number != 3) {
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "C");
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
创建多个Condition可以精准通知
锁的各种现象
代码:
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(() -> {
try {
phone.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
phone.call();
}, "B").start();
}
}
class Phone {
// synchronized 锁的对象是方法的调用者
// 俩个方法用的是同一把锁 谁先拿到谁执行
public synchronized void sendSms() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
public class Test2 {
public static void main(String[] args) throws InterruptedException {
// 2个对象是2个锁 不会相互影响
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
new Thread(() -> {
try {
phone1.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone2.call();
}, "B").start();
}
}
class Phone2 {
// synchronized 锁的对象是方法的调用者
// 俩个方法用的是同一把锁 谁先拿到谁执行
public synchronized void sendSms() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
// 普通方法不受锁的影响
public void hello() {
System.out.println("hello");
}
}
public class Test3 {
public static void main(String[] args) throws InterruptedException {
// 2个对象只有一个Class对象 static 锁的是Class
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(() -> {
try {
phone1.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone2.call();
}, "B").start();
}
}
class Phone3 {
// 把同步方法转为静态方法
// 类一加载就有了 锁的是Class 模板
// Phone3只有一个Class对象
public static synchronized void sendSms() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
public class Test4 {
public static void main(String[] args) throws InterruptedException {
Phone4 phone = new Phone4();
// 先执行打电话 因为锁的不是一个东西
new Thread(() -> {
try {
phone.sendSms();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.call();
}, "B").start();
}
}
class Phone4 {
// 静态的同步方法 锁的Class
public static synchronized void sendSms() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("发短信");
}
// 普通同步方法 锁的对象
public synchronized void call() {
System.out.println("打电话");
}
}