JAVA多线程遇到的synchronized坑

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
如果说的有错误,欢迎大家来指正!

原创文章 57 获赞 9 访问量 5942

猜你喜欢

转载自blog.csdn.net/Cscprx/article/details/104815631