操做的原子性与线程安全

本案例来源于java zone社区,因为源代码里面存在一些本身开发的注解,我暂时没找到相关的文档,因此我作了一些修改。用的都是java SDK的API。 关于概念:java

  • 原子性:即一个操做或者多个操做 要么所有执行而且执行的过程不会被任何因素打断,要么就都不执行。git

  • 线程安全:就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其余线程不能进行访问直到该线程读取完,其余线程才可以使用。不会出现数据不一致或者数据污染。api

  • 线程不安全:就是不提供数据访问保护,有可能出现多个线程前后更改数据形成所获得的数据是脏数据安全

进入正题,若是能够从多个线程调用全部方法而没有外部同步,则类是线程安全的。为了实现这一点,线程安全方法必须是原子的,例如,其余线程只能看到方法以前或以后调用之间的状态。如下示例说明了为何线程安全方法必须是原子的:markdown

public class TR extends FanLibrary {

    private volatile int i = 0;

    public void ss() {
        sleep(100);//为了更容易出现效果
        i++;
    }

    @Before
    public void be() {
        output("before");
    }

    @Test
    public void sdfa() throws InterruptedException {
        Thread first = new Thread(() -> {
            ss();
        });
        Thread second = new Thread(() -> {
            ss();
        });
        first.start();
        second.start();
        first.join();
        second.join();
        output(i);    }

    @After
    public void ds() {
        output("after");
    }
}

控制台输出,如下内容可能会出现,代码中sleep(100)的缘由:多线程

INFO-> before
INFO-> 1
INFO-> after

其中“i++;”至关于“i = i + 1;”包含了“i + 1”和“i =”两个过程,不属于原子操做,因此在多线程访问该方法的时候是不安全的线程

当两个线程同时获取到i = 0的值时,若是此时都没有执行到“i =”这个步骤的时候,那么两个线程等号右边都是1,而后先后执行“i = 1” 这个操做,至关于i最终被两次赋值为1,因此最终“i = 1”code

欢迎有兴趣的童鞋一块儿交流开发

相关文章
相关标签/搜索