当前位置: 首页 > Thinking in Java > 正文
第21章 – 并发 – 共享资源,原子操作
Mar182015
作者:边城网事 发布:2015-03-18 22:09 分类:Thinking in Java 阅读:949 抢沙发
第21章 – 并发 – 共享资源,原子操作
1. 针对每一个类,也有一个锁(作为类的class的一部分),所以,synchronized static 方法可以在类的
范围内防止对static字段的并发访问.(P667)
显然,类class的锁和该类对象的锁不是同一个锁,所以不要在普通对象上调用类的static方法.
2. 原子性可用于除了long和double之外的所有基本变量类型(char,int,short,byte,float,boolean)之上的”简单操作”.(P680)
原子类,来自java.util.concurrent.atomic 包中的类,如AtomicInteger,AtomicReference<V>等.
使用这些类可以获取比volatile更强的读写原子性保证.在多线程写入和读取这些变量时不存在中间状态,即一个线程
更新这些变量之后,更新可以立即在别的线程中生效.不存在 变量值在一个线程中更新了,而另一个线程依旧读到变量的
值更新之前的旧值 这种情况.
可以使用原子类来替代同步(synchronized),以提高性能.
但通常依赖于锁要更安全一些(要么是synchronized关键字,要么显式使用Lock对象)
package concurrency; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.*; //不断产生偶数的类 public class AtomicIntegerTest implements Runnable { private AtomicInteger i = new AtomicInteger(0); public int getValue() { return i.get(); } private void evenIncrement() { i.addAndGet(2); //System.out.println(Thread.currentThread().getName() + ": " + i.get()); } public void run() { while (true) evenIncrement(); } public static void main(String[] args) { new Timer().schedule(new TimerTask() { public void run() { System.err.println("Aborting"); System.exit(0); } }, 5000); // 设置5秒钟后程序自动停止 ExecutorService exec = Executors.newCachedThreadPool(); //使用两个线程同时运行 AtomicIntegerTest ait = new AtomicIntegerTest(); exec.execute(ait); exec.execute(ait); exec.shutdown(); //这里循环检查得到的值,如果获取的不是偶数,则程序终止 //因为这里不可能产生奇数,因此使用上面的Timer在5秒后结束程序 while (true) { int val = ait.getValue(); if ( val % 2 != 0 ) { System.out.println("奇数==============================" + val); System.exit(0); } } } }
3. 线程本地存储java.lang.ThreadLocal
可以将各个线程中变量与其他线程隔离开来,保证当前线程中的这个变量不受其他线程的影响.
package concurrency; // Automatically giving each thread its own storage. import java.util.concurrent.*; class Accessor implements Runnable { private final int id; public Accessor(int idn) { id = idn; } public void run() { while (!Thread.currentThread().isInterrupted()) { ThreadLocalVariableHolder.set(id); ThreadLocalVariableHolder.increment(); System.out.println(this); Thread.yield(); } } public String toString() { return "#" + id + ": " + ThreadLocalVariableHolder.get(); } } public class ThreadLocalVariableHolder { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() { // private Random rand = new Random(47); protected synchronized Integer initialValue() { return 20; } }; public static void increment() { value.set(value.get() + 1); } public static int get() { return value.get(); } public static void set(int i) { value.set(i); } public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) exec.execute(new Accessor(i)); TimeUnit.MICROSECONDS.sleep(200); // Run for a while exec.shutdownNow(); // All Accessors will quit } }
赞 赏
微信赞赏 支付宝赞赏
本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2144.html | 边城网事