线程的同步和死锁1

2019-01-24  本文已影响0人  秋笙fine

本篇是为了同步问题的引出。

实际上所谓的同步指的就是多个线程访问同一资源所引出的问题。

范例:观察非同步情况下的操作(多人卖票问题)

package TestDemo;



class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中

    private int ticket=5;

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(this.ticket>0)
            System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
        }
    }   
}

public class TestDemo{
    
    public static void main(String[] args)throws Exception{
        MyThread mt=new MyThread();
    
        new Thread(mt,"seller A").start();
        new Thread(mt,"seller B").start();
        new Thread(mt,"seller C").start();
        new Thread(mt,"seller D").start();


    }
    
}
image.png

此时没有问题出现是因为在一个JVM进程下运行,并且没有受到任何影响,如果要想观察到问题,可以加入一个延迟。

package TestDemo;



class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中

    private int ticket=5;

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(this.ticket>0){
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            
            System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
            
            }
        }
    }   
}

public class TestDemo{
    
    public static void main(String[] args)throws Exception{
        MyThread mt=new MyThread();
    
        new Thread(mt,"seller A").start();
        new Thread(mt,"seller B").start();
        new Thread(mt,"seller C").start();
        new Thread(mt,"seller D").start();


    }
    
}

发现出现了脏数据。


image.png

不仅出现了重复数据,还出现了负数,这就是不同步的状况,整个卖票的步骤分为两步:
第一步:判断是否还有剩余的票数
第二步:减少剩余票数


image.png

我们可以将中间的休眠想象成高并发下的程序运行,压力增大情况下,如果不对票数进行同步加锁,就会出现脏数据,设想一下,12306抢票的时候,高并发情况下,票数需要加锁,否则就会出现票数为负的情况,或者同一张票卖给了两人,是灾难性的。因而线程安全的核心思想:"要么只读,要么加锁。"

上一篇 下一篇

猜你喜欢

热点阅读