Java线程安全问题

Java线程安全问题

1 线程不安全演示

public class Demo {
    public static void main(String[] args) {
        //线程不安全
        Runnable run = new Ticket();
        new Thread(run).start();
        new Thread(run).start();
        new Thread(run).start();

    }

    static class Ticket implements Runnable{
        //票数
        private int count = 10;
        @Override
        public void run() {
            while (count > 0){
                //卖票
                System.out.println("正在准备卖票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println("出票成功,余票:" + count);

            }
        }
    }
}

显示结果:出现线程不安全问题

正在准备卖票
正在准备卖票
正在准备卖票
出票成功,余票:9
正在准备卖票
出票成功,余票:7
正在准备卖票
出票成功,余票:8
正在准备卖票
出票成功,余票:6
正在准备卖票
出票成功,余票:5
正在准备卖票
出票成功,余票:4
正在准备卖票
出票成功,余票:3
正在准备卖票
出票成功,余票:2
正在准备卖票
出票成功,余票:2
正在准备卖票
出票成功,余票:1
正在准备卖票
出票成功,余票:0
出票成功,余票:-1
出票成功,余票:-2

2 同步代码块

格式

synchronize(锁对象){
	// 线程执行的操作
	
}

示例

public class Demo {
   
    public static void main(String[] args) {
        Runnable run = new Ticket();
        new Thread(run, "窗口1").start();
        new Thread(run, "窗口2").start();
        new Thread(run, "窗口3").start();

    }

    static class Ticket implements Runnable{
        //票数
        private int count = 10;
        private Object o = new Object();
        @Override
        public void run() {
                while (true){
                    synchronized (o) {
                        if (count > 0) {
                            //卖票
                            System.out.println(Thread.currentThread().getName() + "正在准备卖票");
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            count--;
                            System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count);

                        }else {
                            break;
                        }

                    }
                }

        }
    }
}

显示结果

窗口1正在准备卖票
窗口1出票成功,余票:9
窗口1正在准备卖票
窗口1出票成功,余票:8
窗口1正在准备卖票
窗口1出票成功,余票:7
窗口1正在准备卖票
窗口1出票成功,余票:6
窗口1正在准备卖票
窗口1出票成功,余票:5
窗口3正在准备卖票
窗口3出票成功,余票:4
窗口3正在准备卖票
窗口3出票成功,余票:3
窗口3正在准备卖票
窗口3出票成功,余票:2
窗口3正在准备卖票
窗口3出票成功,余票:1
窗口3正在准备卖票
窗口3出票成功,余票:0

注意:

  • Java中任何对象都可以当做锁对象
  • 对于不同的线程需要使用同一个锁对象

3 同步方法

格式

权限修饰符 synchronize 返回值类型 方法名(){

}

示例

public class Demo7 {

    public static void main(String[] args) {
        Runnable run = new Ticket();
        new Thread(run, "窗口1").start();
        new Thread(run, "窗口2").start();
        new Thread(run, "窗口3").start();

    }

    static class Ticket implements Runnable{
        //票数
        private int count = 10;
        @Override
        public void run() {
                while (true){
                    boolean flag = sale();
                    if (!flag) break;
                }

        }
        public synchronized boolean sale(){
            if (count > 0) {
                //卖票
                System.out.println(Thread.currentThread().getName() + "正在准备卖票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count);

                return true;
            }
            return false;
        }
    }
}

显示结果

窗口1正在准备卖票
窗口1出票成功,余票:9
窗口1正在准备卖票
窗口1出票成功,余票:8
窗口1正在准备卖票
窗口1出票成功,余票:7
窗口1正在准备卖票
窗口1出票成功,余票:6
窗口1正在准备卖票
窗口1出票成功,余票:5
窗口1正在准备卖票
窗口1出票成功,余票:4
窗口1正在准备卖票
窗口1出票成功,余票:3
窗口1正在准备卖票
窗口1出票成功,余票:2
窗口1正在准备卖票
窗口1出票成功,余票:1
窗口1正在准备卖票
窗口1出票成功,余票:0

注意

同步方法中的锁对象是this,即当前对象。如果是静态方法则是类名.class。

4 显示锁

格式

Lock l = new ReentrantLock();
l.lock();
//线程执行任务
l.unlock();

示例

public class Demo {
    public static void main(String[] args) {
        Runnable run = new Ticket();
        new Thread(run, "窗口1").start();
        new Thread(run, "窗口2").start();
        new Thread(run, "窗口3").start();

    }

    static class Ticket implements Runnable{
        //票数
        private int count = 10;
        private Lock l = new ReentrantLock();

        @Override
        public void run() {


            while (true){
                l.lock();
                if (count > 0) {
                    //卖票
                    System.out.println(Thread.currentThread().getName() + "正在准备卖票");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count--;
                    System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count);

                }else {
                    break;
                }
                l.unlock();

            }

        }


    }
}

显示结果

窗口1正在准备卖票
窗口1出票成功,余票:9
窗口1正在准备卖票
窗口1出票成功,余票:8
窗口1正在准备卖票
窗口1出票成功,余票:7
窗口1正在准备卖票
窗口1出票成功,余票:6
窗口1正在准备卖票
窗口1出票成功,余票:5
窗口1正在准备卖票
窗口1出票成功,余票:4
窗口1正在准备卖票
窗口1出票成功,余票:3
窗口1正在准备卖票
窗口1出票成功,余票:2
窗口1正在准备卖票
窗口1出票成功,余票:1
窗口1正在准备卖票
窗口1出票成功,余票:0

5 公平锁与不公平锁

公平锁:先来先得,排队抢占锁

不公平锁:随机抢占锁

创建锁对象是默认是不公平锁,在创建显示锁对象时,构造方法中传入true可将锁对象设置为公平锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值