生产者消费者模型锁Integer类型时遇到的问题

题目
使用生产者和消费者模式实现,交替输出:
    假设只有两个线程,输出以下结果:
        t1-->1
        t2-->2
        t1-->3
        t2-->4
        t1-->5
        t2-->6
        ....

        要求:必须交替,并且t1线程负责输出奇数。t2线程负责输出偶数。
        两个线程共享一个数字,每个线程执行时都要对这个数字进行:++

代码

一开始采用的Integer类型:


public class Homework1 {
    public static void main(String[] args)throws Exception {
        Integer integer=new Integer(0);
        Thread t1=new Thread(new SCZ(integer));
        Thread t2=new Thread(new XFZ(integer));
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        Thread.sleep(1);
        t2.start();
    }
}

class SCZ implements Runnable {
    public static Integer integer;

    public SCZ() {
    }

    public SCZ(Integer integer) {
        this.integer = integer;
    }

    @Override
    public void run() {
        while (true){
            synchronized (integer) {
                //停止生产的条件
                System.out.println(System.identityHashCode(integer));//402421002
                if (integer % 2 == 1) {

                    try {
                        integer.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                integer=integer+1;
                System.out.println(Thread.currentThread().getName() + "-->" + integer);
                System.out.println(System.identityHashCode(integer));//423332229
                integer.notifyAll();
            }
        }
    }
}
class XFZ implements Runnable{
    public static Integer integer;
    public XFZ() {
    }

    public XFZ(Integer integer) {
        this.integer = integer;
    }
    @Override
    public void run() {

        while (true){
            synchronized (integer) {
                System.out.println(System.identityHashCode(integer));//402421002
                //停止消费的条件
                if (integer % 2 == 0) {
                    try {
                        integer.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                integer=integer+1;
                System.out.println(Thread.currentThread().getName() + "-->" + integer);
                integer.notify();
            }
        }
    }
}

报错如下:

生产者消费者模型锁Integer类型时遇到的问题

后来尝试输出生产者和消费者的实际地址,发现一致。输出生产者加1后的实际地址,发现此时的integer对象地址已经发生改变,而消费者拿到的是之前的地址,因此唤醒和等待对象的内存地址不一致,唤了个寂寞。

后来尝试了创建Num类,使用成员变量记录数据,锁num对象,没有问题。

public class Homework2 {
    public static void main(String[] args) {
        Num num=new Num(0);
        Thread t1=new Thread(new SCZ(num));
        Thread t2=new Thread(new XFZ(num));
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }
}
class Num{
    int i;
    public Num() {
    }

    public Num(int i) {
        this.i = i;
    }
}

class SCZ implements Runnable {
    private Num num;

    public SCZ() {
    }

    public SCZ(Num num) {
        this.num = num;
    }

    @Override
    public void run() {
        while (true){
            synchronized (num) {
                //停止生产的条件
                if (num.i % 2 == 1) {
                    try {
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                num.i++;
                System.out.println(Thread.currentThread().getName() + "-->" + num.i);
                num.notify();
            }
        }
    }
}
class XFZ implements Runnable{
    private Num num;

    public XFZ() {
    }

    public XFZ(Num num) {
        this.num = num;
    }

    @Override
    public void run() {
        while (true){
            synchronized (num) {
                //停止生产的条件
                if (num.i % 2 == 0) {
                    try {
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                num.i++;
                System.out.println(Thread.currentThread().getName() + "-->" + num.i);
                num.notify();
            }
        }
    }
}

输出如下:

生产者消费者模型锁Integer类型时遇到的问题

 

总结

基本数据类型的包装类不适合作为锁,尽量不要使用。

上一篇:Shiro(一)——简介、Spring + MVC + shiro 整合


下一篇:opencv for android sample导入有误