本案例来源于java zone社区,由于源代码里面存在一些自己开发的注解,我暂时没找到相关的文档,所以我做了一些修改。用的都是java SDK的API。
关于概念:
进入正题,如果可以从多个线程调用所有方法而没有外部同步,则类是线程安全的。为了实现这一点,线程安全方法必须是原子的,例如,其他线程只能看到方法之前或之后调用之间的状态。以下示例说明了为什么线程安全方法必须是原子的:
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-> beforeINFO-> 1INFO-> after
其中“i++;”相当于“i = i + 1;”包含了“i + 1”和“i =”两个过程,不属于原子操作,所以在多线程访问该方法的时候是不安全的。
当两个线程同时获取到i = 0的值时,如果此时都没有执行到“i =”这个步骤的时候,那么两个线程等号右边都是1,然后前后执行“i = 1” 这个操作,相当于i最终被两次赋值为1,所以最终“i = 1”