同步方法

public class SellTickets implements Runnable{
    //共有100张票
    private int tickets = 100;
    private Object obj = new Object();
    private int x = 0;

    @Override
    public void run() {
        while (true) {
            //锁多条语句操作共享数据,当线程1运行进入锁时,对外相当于被锁起来,其他线程只能等待线程1运行结束才能进入。
            if (x % 2 == 0) {
                synchronized (obj) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }
                }
            } else {
                synchronized (obj) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }
                }
            }
            x++;
        }
    }
}

将上述代码中else部分使用一个单独的方法并加锁来实现:

private synchronized void SellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}

此时来运行卖票测试类:

此时仍然会发生数据安全问题,原因在于synchronized关键字在锁方法时,锁的是一个方法,其对应的对象应该能表示本方法的——this,而在if中锁的对象仍然还是Object,所以会发生问题,将if语句中锁的对象修改为this后的代码:

synchronized (this) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }

此时的运行结果:

没有出现数据安全问题

那么如果我将synchronized加到静态方法上,锁对应的对象应该是什么?

分析staic关键字可以猜到,锁静态方法时,应该是要锁一个与类相关的对象——类名.class(字节码文件)

public class SellTickets implements Runnable{
    //共有100张票
    private static int tickets = 100;
    private Object obj = new Object();
    private int x = 0;

    @Override
    public void run() {
        while (true) {
            //锁多条语句操作共享数据,当线程1运行进入锁时,对外相当于被锁起来,其他线程只能等待线程1运行结束才能进入。
            if (x % 2 == 0) {
                synchronized (SellTickets.class) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }
                }
            } else {
                SellTicket();
            }
            x++;
        }
    }

    private static synchronized void SellTicket() {
        if (tickets > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
            tickets--;
        }
    }
}
View Code

 运行结果也是没有问题的。

posted @ 2020-04-29 17:34  硬盘红了  阅读(127)  评论(0编辑  收藏  举报