Java Multithreading - New Features - Atomic Weight

The so-called atomic quantity is that the operation of the operation variable is "atomic", the operation is not subdivided, and therefore is thread-safe.

Why use atomic variables? The reason is that operations on a single variable by multiple threads can also cause problems. Before Java5, the security problem of concurrent access can be solved by volatile and synchronized keywords, but this is too troublesome.
After Java5, the toolkit java.util.concurrent.atomic for single-variable multi-threaded concurrent safe access is specially provided, and the classes in it are also very simple.

copy code
package cn.thread;

import java.util.concurrent.atomic.AtomicLong;

public  class AtomicRunnable implements Runnable {
     private  static AtomicLong aLong = new AtomicLong(10000); // Atomic quantity, each thread can freely operate 
    private String name; // operator 
    private  int x; // operation amount 

    AtomicRunnable(String name, int x) {
         this .name = name;
         this .x = x;
    }

    public void run() {
        System.out.println(name + "executed " + x + ", current balance: " + aLong.addAndGet(x));
    }

}
copy code
copy code
package cn.thread;

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

/**
 * Multithreading - Atomic
 *
 * @author Lin Jiqin
 * @version 1.0 2013-7-26 下午04:13:45
 */
public class ThreadAtomicTest {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        Runnable t1 = new AtomicRunnable("张三", 2000);
        Runnable t2 = new AtomicRunnable("李四", 3600);
        Runnable t3 = new AtomicRunnable("王五", 2700);
        Runnable t4 = new AtomicRunnable("老张", 600);
        Runnable t5 = new AtomicRunnable("老牛", 1300);
        Runnable t6 = new AtomicRunnable("Fat Man", 800 );
         // Execute each thread 
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        pool.execute(t6);
        // Close the thread pool 
        pool.shutdown();
    }

     
}
copy code

operation result:

张三执行了2000,当前余额:12000
王五执行了2700,当前余额:14700
老张执行了600,当前余额:15300
老牛执行了1300,当前余额:16600
胖子执行了800,当前余额:17400
李四执行了3600,当前余额:21000
张三执行了2000,当前余额:12000
李四执行了3600,当前余额:15600
老张执行了600,当前余额:18900
老牛执行了1300,当前余额:20200
胖子执行了800,当前余额:21000
王五执行了2700,当前余额:18300
张三执行了2000,当前余额:12000
王五执行了2700,当前余额:14700
李四执行了3600,当前余额:18300
老牛执行了1300,当前余额:20200
胖子执行了800,当前余额:21000
老张执行了600,当前余额:18900

从运行结果可以看出,虽然使用了原子量,但是程序并发访问还是有问题,那究竟问题出在哪里了?

这里要注意的一点是,原子量虽然可以保证单个变量在某一个操作过程的安全,但无法保证你整个代码块,或者整个程序的安全性。因此,通常还应该使用锁等同步机制来控制整个程序的安全性。

下面是对这个错误修正:

copy code
package cn.thread;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;

public class AtomicRunnable2 implements Runnable {
    private static AtomicLong aLong = new AtomicLong(10000); // 原子量,每个线程都可以自由操作
    private String name; // 操作人
    private int x; // 操作数额
    private Lock lock;

    AtomicRunnable2(String name, int x, Lock lock) {
        this.name = name;
        this.x = x;
        this.lock=lock;
    }

    public void run() {
        lock.lock();
        System.out.println(name + "执行了" + x + ",当前余额:" + aLong.addAndGet(x));
        lock.unlock();
    }

}
copy code
copy code
package cn.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 多线程-原子量
 * 
 * @author 林计钦
 * @version 1.0 2013-7-26 下午04:13:45
 */
public class ThreadAtomicTest2 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        Lock lock = new ReentrantLock(false);
        Runnable t1 = new AtomicRunnable2("张三", 2000, lock);
        Runnable t2 = new AtomicRunnable2("李四", 3600, lock);
        Runnable t3 = new AtomicRunnable2("王五", 2700, lock);
        Runnable t4 = new AtomicRunnable2("老张", 600, lock);
        Runnable t5 = new AtomicRunnable2("老牛", 1300, lock);
        Runnable t6 = new AtomicRunnable2("胖子", 800, lock);
        // 执行各个线程
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        pool.execute(t6);
        // 关闭线程池
        pool.shutdown();
    }

}
copy code

运行结果:

Li Si executed 3600, current balance: 13600 
Wang Wu executed 2700, current balance: 16300 Lao 
Zhang 
executed 600, current balance: 16900 
Lao Niu executed 1300, current balance: 18200 
Fatty executed 800, current balance: 19000 Three executed 2000, current balance: 21000

An object lock is used here to control access to concurrent code. No matter how many times it is run and what the order of execution is, the final balance is 21000, which is correct.

The usage of atomic weight is very simple, the key is the understanding of atomic weight, atomic only guarantees the atomicity of variable operation, but the whole program also needs to consider thread safety.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326228468&siteId=291194637