首页 > java AtomicInteger线程安全问题

java AtomicInteger线程安全问题

public class TTTT implements Runnable{

public static AtomicInteger ato = new AtomicInteger(1);
int i = 1;
public static void main(String[] args) {
    TTTT t = new TTTT();
    for (int i = 0;i<100; i++){
        new Thread(t).start();
    }
}

public void rrrr() throws Exception{
    Thread.sleep(100);
    int preVal = ato.get();
    int val = ato.incrementAndGet();
    System.out.println(preVal+" ########### "+val);
}

@Override public void run() {
    try {
        rrrr();
    } catch (Exception e){

    }
}

}

AtomicInteger 的incrementAndGet是线程安全的计数方法
上面代码执行结果是:

1 ########### 4
5 ########### 6
1 ########### 3
9 ########### 10
9 ########### 11
13 ########### 14
16 ########### 18
1 ########### 2
8 ########### 9
6 ########### 7
4 ########### 5
7 ########### 8
18 ########### 19
16 ########### 17
14 ########### 15
15 ########### 16
12 ########### 13
11 ########### 12
19 ########### 21
21 ########### 22
22 ########### 23
19 ########### 20
23 ########### 24
24 ########### 25

无法保证顺序,线程安全体现在哪里呢


简单说说吧。

  1. 线程安全是在多线程环境下,数据的增加和减少是安全的,例子中数据不重复就代表了线程安全了。
    2.顺序问题是有线程执行的顺序决定的,和线程安全没关系


Atomic类中的value值都是一些被volatile标注的类型, volatile是java提供的轻量级变量同步机制,它确保了变量可见性,即任何一个线程修改了volatile修饰的变量,其他线程将立即可见.对于普通变量因为存在主内存和工作区内存的复制和同步,所以无法具备此特性.volatile变量存储在主内中,任何线程需要使用此变量时,必须再次read,因为其他线程对此变量的更改,将会被其他线程在使用此变量时立即获得新值.
volatile只是保证了可见性,但是它并非线程安全,因为如果线程一旦read到此值然后进行计算,在尚未write到主内存时其他线程也做了同样的操作,那么volatile变量的最终结果将无法达到预期..如果期望volatile变量线程安全,必须同步或者CAS.volatile变量操作时,read->load->use三个操作是连续的,assign->store->write三个操作是连续的.
里面采用的是CAS(compareAndSet)的值替换方法,像一种"乐观锁",通过"比较"-"更新"这种无阻塞的手段实现数据在多线程下的"安全性".


直接上代码,你用线程池当中的Executors.newSingleThreadExecutor();代码如下:

package test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class TestAtomicInteger implements Runnable{
    public static AtomicInteger atomic = new AtomicInteger();
    int i = 0;
    @Override
    public void run(){
        try {
            Thread.sleep(100);
            int preVal = atomic.get();
            int val = atomic.incrementAndGet();
            System.out.println(preVal+" ########### "+val);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        TestAtomicInteger test = new TestAtomicInteger();
        ExecutorService executor = Executors.newSingleThreadExecutor();
        for(int i = 0;i < 100; i++){
            executor.execute(test);
        }
    }
}

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


你输出的右边不会重复也不会漏,这就是它的线程安全保证


AtomicInteger 的incrementAndGet 保证对整数的递增和获取是原子的,

  1. 值+1

  2. 返回值

一个线程在这两个操作之间不会强行插入另外的线程

你要保证顺序,那么需要的是线程互斥


AtomicInteger是一个原子类,顾名思义,它能保证一些操作是原子性的,比如说++、--等操作,这些操作在多线程的情况并不是线程安全的,但是使用原子类可以保证这些操作的原子性,从而来保证线程的安全性。

【热门文章】
【热门文章】