【Java多线程】使用同步代码块解决线程安全问题

public class ThreadTest implements Runnable {

    private int trainCount = 100;
    private Object lock = new Object();//实例化一个对象当作锁

    @Override
    public void run() {
        while (trainCount > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                sell();
        }

    }

    public void sell () {
        synchronized (lock) {
            if (trainCount > 0) {
                System.out.println(Thread.currentThread().getName() + " Sell a ticket:" + (100 - trainCount + 1));
                trainCount--;
            }
        }
    }


    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest, "窗口①");
        Thread thread2 = new Thread(threadTest, "窗口②");
        thread.start();
        thread2.start();

    }
}

//运行结果
//窗口① Sell a ticket:1
//        窗口② Sell a ticket:2
//        窗口① Sell a ticket:3
//        窗口② Sell a ticket:4
//        窗口① Sell a ticket:5
//        窗口② Sell a ticket:6
//        窗口① Sell a ticket:7
//        窗口② Sell a ticket:8
//        窗口① Sell a ticket:9
//        窗口② Sell a ticket:10
//        窗口① Sell a ticket:11
//        窗口② Sell a ticket:12
//        窗口② Sell a ticket:13
//        窗口① Sell a ticket:14
//        窗口① Sell a ticket:15
//        窗口② Sell a ticket:16
//        窗口② Sell a ticket:17
//        窗口① Sell a ticket:18
//        窗口① Sell a ticket:19
//        窗口② Sell a ticket:20
//        窗口① Sell a ticket:21
//        窗口② Sell a ticket:22
//        窗口② Sell a ticket:23
//        窗口① Sell a ticket:24
//        窗口① Sell a ticket:25
//        窗口② Sell a ticket:26
//        窗口① Sell a ticket:27
//        窗口② Sell a ticket:28
//        窗口① Sell a ticket:29
//        窗口② Sell a ticket:30
//        窗口② Sell a ticket:31
//        窗口① Sell a ticket:32
//        窗口① Sell a ticket:33
//        窗口② Sell a ticket:34
//        窗口① Sell a ticket:35
//        窗口② Sell a ticket:36
//        窗口② Sell a ticket:37
//        窗口① Sell a ticket:38
//        窗口① Sell a ticket:39
//        窗口② Sell a ticket:40
//        窗口② Sell a ticket:41
//        窗口① Sell a ticket:42
//        窗口① Sell a ticket:43
//        窗口② Sell a ticket:44
//        窗口② Sell a ticket:45
//        窗口① Sell a ticket:46
//        窗口① Sell a ticket:47
//        窗口② Sell a ticket:48
//        窗口① Sell a ticket:49
//        窗口② Sell a ticket:50
//        窗口② Sell a ticket:51
//        窗口① Sell a ticket:52
//        窗口① Sell a ticket:53
//        窗口② Sell a ticket:54
//        窗口② Sell a ticket:55
//        窗口① Sell a ticket:56
//        窗口① Sell a ticket:57
//        窗口② Sell a ticket:58
//        窗口① Sell a ticket:59
//        窗口② Sell a ticket:60
//        窗口① Sell a ticket:61
//        窗口② Sell a ticket:62
//        窗口② Sell a ticket:63
//        窗口① Sell a ticket:64
//        窗口① Sell a ticket:65
//        窗口② Sell a ticket:66
//        窗口② Sell a ticket:67
//        窗口① Sell a ticket:68
//        窗口① Sell a ticket:69
//        窗口② Sell a ticket:70
//        窗口② Sell a ticket:71
//        窗口① Sell a ticket:72
//        窗口② Sell a ticket:73
//        窗口① Sell a ticket:74
//        窗口① Sell a ticket:75
//        窗口② Sell a ticket:76
//        窗口② Sell a ticket:77
//        窗口① Sell a ticket:78
//        窗口② Sell a ticket:79
//        窗口① Sell a ticket:80
//        窗口① Sell a ticket:81
//        窗口② Sell a ticket:82
//        窗口① Sell a ticket:83
//        窗口② Sell a ticket:84
//        窗口② Sell a ticket:85
//        窗口① Sell a ticket:86
//        窗口① Sell a ticket:87
//        窗口② Sell a ticket:88
//        窗口① Sell a ticket:89
//        窗口② Sell a ticket:90
//        窗口① Sell a ticket:91
//        窗口② Sell a ticket:92
//        窗口① Sell a ticket:93
//        窗口② Sell a ticket:94
//        窗口① Sell a ticket:95
//        窗口② Sell a ticket:96
//        窗口① Sell a ticket:97
//        窗口② Sell a ticket:98
//        窗口② Sell a ticket:99
//        窗口① Sell a ticket:100
//
//        Process finished with exit code 0

上面代码使用了synchronized代码块进行数据的同步,使用synchronized的时候不要全部代码用synchronized代码块包裹,只要包裹可能会出现线程安全问题的地方就行了 锁:
比如上厕所锁了门,必须要等里面的认出来了其他人才能抢厕所

使用synchronized的条件:
1.必须有两个线程以上,并且需要发生同步 2.多个线程同步,必须用同一把锁 3.保证只有一个线程进行执行

原理:
1.当一个线程拿到锁了,其他线程已经有cpu执行,需要排队等待其他线程释放锁。 2.代码执行完毕或者抛出异常是就会释放锁 3.锁被释放掉的话,其他贤臣刚开始抢夺锁进去同步中区

缺点:
死锁问题 效率非常低,因为多个线程还要抢夺锁耗费资源

保证线程的原子性 原子性:是指一个操作是不可中断的。即使是多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。     比如,对于一个静态全局变量int i,两个线程同时对它赋值,线程A给他赋值为1,线程B给他赋值为-1。那么不管这两个线程     以何种方式。何种步调工作,i的值要么是1,要么是-1.线程A和线程B之间是没有干扰的。这就是原子性的一个特点,不可被中断。

发表评论

邮箱地址不会被公开。 必填项已用*标注