今天我们来看看Java中的AericInteger
。原子操作 在单个任务单元中执行,不受其他操作的干扰。原子操作在多线程环境中是必要的,以避免数据不一致。
原子整型
让我们创建一个简单的多线程程序,其中每个线程将共享的
Count
变量递增4次。因此,如果有两个线程,在它们完成后,Count
值应该是8。
1package com.journaldev.concurrency;
2
3public class JavaAtomic {
4
5 public static void main(String[] args) throws InterruptedException {
6
7 ProcessingThread pt = new ProcessingThread();
8 Thread t1 = new Thread(pt, "t1");
9 t1.start();
10 Thread t2 = new Thread(pt, "t2");
11 t2.start();
12 t1.join();
13 t2.join();
14 System.out.println("Processing count=" + pt.getCount());
15 }
16
17}
18
19class ProcessingThread implements Runnable {
20 private int count;
21
22 @Override
23 public void run() {
24 for (int i = 1; i < 5; i++) {
25 processSomething(i);
26 count++;
27 }
28 }
29
30 public int getCount() {
31 return this.count;
32 }
33
34 private void processSomething(int i) {
35 // processing some job
36 try {
37 Thread.sleep(i * 1000);
38 } catch (InterruptedException e) {
39 e.printStackTrace();
40 }
41 }
42
43}
如果你要运行上面的程序,你会注意到Count
的值在5,6,7,8之间。原因是count++ 不是原子操作。因此,当一个线程读取它的值并将其递增1时,另一个线程已经读取了较旧的值,从而导致错误的结果。为了解决这个问题,我们将必须确保计数上的增量操作是原子的,我们可以使用Synchronization,但是Java 5java.util.concurent.topic
为int和long提供了包装类,可以用来在不使用同步的情况下实现这种原子操作。
Java原子整型示例
下面是更新后的程序,它将始终输出计数值为8,因为AericInteger
方法incrementAndGet()
自动将当前值递增1。
1package com.journaldev.concurrency;
2
3import java.util.concurrent.atomic.AtomicInteger;
4
5public class JavaAtomic {
6
7 public static void main(String[] args) throws InterruptedException {
8
9 ProcessingThread pt = new ProcessingThread();
10 Thread t1 = new Thread(pt, "t1");
11 t1.start();
12 Thread t2 = new Thread(pt, "t2");
13 t2.start();
14 t1.join();
15 t2.join();
16 System.out.println("Processing count=" + pt.getCount());
17 }
18}
19
20class ProcessingThread implements Runnable {
21 private AtomicInteger count = new AtomicInteger();
22
23 @Override
24 public void run() {
25 for (int i = 1; i < 5; i++) {
26 processSomething(i);
27 count.incrementAndGet();
28 }
29 }
30
31 public int getCount() {
32 return this.count.get();
33 }
34
35 private void processSomething(int i) {
36 // processing some job
37 try {
38 Thread.sleep(i * 1000);
39 } catch (InterruptedException e) {
40 e.printStackTrace();
41 }
42 }
43
44}
使用并发类进行原子操作的好处是我们不需要担心同步。这提高了代码的可读性,并降低了出错的机会。此外,原子操作并发类被认为比涉及锁定资源的同步更高效。