synchronized 锁住的是对象!! 一定是所有线程间共享的同一个对象!!!!
今天在写多线程代码的时候,找了好久的一个bug,
下面是错误代码
package mianshi;
public class threadTest {
private Integer product = 5;
// private String product = "lock";
public static void main(String[] args) {
threadTest t = new threadTest();
new Thread(t.new Product(), "Producter1").start();
new Thread(t.new Consumer(), "Consumer1").start();
new Thread(t.new Product(), "Producter2").start();
new Thread(t.new Consumer(), "Consumer2").start();
}
class Product implements Runnable {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (product) {
while (product == 5) {
try {
System.out.println("商品够多啦,请等等在生产");
product.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product++;
System.out.println(Thread.currentThread().getName() + "生产一个商品");
System.out.println("当前有" + product + "个商品");
product.notifyAll();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (product) {
while (product == 0) {
try {
System.out.println("当前没有商品,请耐心等待");
product.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product--;
System.out.println(Thread.currentThread().getName() + "消费一个商品");
System.out.println("当前有" + product + "个商品");
product.notifyAll();
}
}
}
}
}
这里是正确代码
package mianshi;
public class threadTest {
private Integer product = 5;
private String lock = "lock";
public static void main(String[] args) {
threadTest t = new threadTest();
new Thread(t.new Product(), "Producter1").start();
new Thread(t.new Consumer(), "Consumer1").start();
new Thread(t.new Product(), "Producter2").start();
new Thread(t.new Consumer(), "Consumer2").start();
}
class Product implements Runnable {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
while (product == 5) {
try {
System.out.println("商品够多啦,请等等在生产");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product++;
System.out.println(Thread.currentThread().getName() + "生产一个商品");
System.out.println("当前有" + product + "个商品");
lock.notifyAll();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
while (product == 0) {
try {
System.out.println("当前没有商品,请耐心等待");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product--;
System.out.println(Thread.currentThread().getName() + "消费一个商品");
System.out.println("当前有" + product + "个商品");
lock.notifyAll();
}
}
}
}
}
其实错误就在于synchronized (lock) 锁住的这个对象!我直线写的是synchronized (product),那么这会导致一个什么情况呢?
因为锁住的一定要是线程间共享的同一个变量,同一个!!!!
那有人会说了,那product,也是同一个变量啊?
不!! Integer这种属于包装类,你更改了它的值就会在堆中重新创建一个对象,也就是说product=1是一个对象,更改后product=2还是一个变量,所以说线程之间锁的不是同一个变量,那么更改之后呢? 因为没有对lock进行修改,所以说没有错误!
还有一个需要注意的点就是这里面判断product的时候一定要用while,为了防止虚假唤醒,最好用while替换if
如果说的有错误,欢迎大家来指正!