Java多线程中的原子类

March 9, 2015

先来看没有加锁的情况:

这个例子中我们想在pt类中对count进行累加, 两个线程各4次,最后应该输出8, 然而这个例子输出的结果从4-8都会出现,这就是典型的没有同步的例子.

public class Main  {

public static void main(String[] args) throws Exception {

ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());

}
}
class ProcessingThread implements Runnable {
private int count;


@Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count++; //非原子操作
}
}


public synchronized int getCount() {
return this.count;
}


private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

再来看看原子类:

这个例子中,我们使用的AtomicInteger的两个操作是原子操作,因此不会出现数据不一致的情况.

import java.util.concurrent.atomic.AtomicInteger;


public class JavaAtomic {

public static void main(String[] args) throws InterruptedException {

ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());
}

}


class ProcessingThread implements Runnable {
private AtomicInteger count = new AtomicInteger();


@Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count.incrementAndGet(); //原子操作
}
}


public int getCount() {
return this.count.get(); // 原子操作
}


private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

synchronized例子

和上例结果一样,我们用synchronized关键字来实现

 
public class JavaAtomic {

public static void main(String[] args) throws InterruptedException {

ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());
}

}


class ProcessingThread implements Runnable {
private int count;


@Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
synchronized(this) {
count++;
}
}
}


public int getCount() {
return this.count; // 原子操作
}


private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}