Java

例示CyclicBarrier的使用

package player.kent.chen.learn.barrier; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class HelloBarrier { /** * 大家都到齐后,再一起开火 */ private static final class FireTogether implements Runnable { private CyclicBarrier barrier; public FireTogether(CyclicBarrier barrier) { super(); this.barrier = barrier; } public void run() { try { barrier.await(); //等别的线程到达集合点 System.out.println(Thread.currentThread().getName() + ": 哥开火了!"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (BrokenBarrierException …

例示CyclicBarrier的使用 Read More »

例示CountDownLatch的使用

CountDownLatch可用于一个线程等待另外一些线程做了一些事后再做自己的事。做事的线程做完事后报一下数:将一个初数值减1,等这个数值变成0时,等待的线程就可以做自己的事。 用join()也能完成相同的目标。但join()意味着必须等待做事线程终止自己才能动手,CountDownLatch没有这个限制,做事线程再报完数后还可以继续做自己的事。 执行结果: 我是乞丐,要钱吃饭 walker0 已经动身了 walker1 已经动身了 walker2 已经动身了 我是行人walker0  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是行人walker1  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是行人walker2  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是乞丐,钱要够了,现在去买吃的 我是行人walker0  给完钱后,我在无边的人海中继续前行直到永远。。。 我是行人walker1  给完钱后,我在无边的人海中继续前行直到永远。。。 我是行人walker2  给完钱后,我在无边的人海中继续前行直到永远。。。 同时各行人线程仍处于alive状态。

ReadWriteLock代码示例

ReadWriteLock的契约是:    1. 读、写都要先获得相应的锁    2. 如果在共享数据上已经加了读锁,则其他线程可以继续加读锁,再不能加写锁;也就是说,你读时别人也可以读,但不能写    3. 如果已经加了写锁,则其他线程不能加任何锁;也就是说,你在写时别人不能写也不能读 可见ReadWriteLock适用于读多写少的情形。 下面的代码例子是从《JAVA并发编程实践》中抄来的。注意我们一般用可重入的ReadWriteLock,即ReentrantReadWriteLock

Java Semaphore例子

package player.kent.chen.learn.semaphore; import java.util.concurrent.Semaphore; public class HelloSemaphore { private static final class Room { //信号量作为共享资源的属性 private Semaphore semaPhore = new Semaphore(3, true); //每次只允许3个人在房内 public void take() throws InterruptedException { try { semaPhore.acquire(); System.out.println(Thread.currentThread().getName() + " is now in the room"); Thread.sleep(3000); } finally { semaPhore.release(); } } } private static final class Guest implements Runnable …

Java Semaphore例子 Read More »

例示:volatile是否只适用于primitve type ?

volatile是否只适用于primitve type? 也就是说,java对象是否也存在 主内存+工作内存副本这样的机制? 结论是:volatile对object reference也适用。 具体来说, 如果一个变量原来是指向对象A的,一个线程把它指向对象B后,另一个线程并不能感知这种变化。 例如, package player.kent.chen.learn.hivolatile; /** * 循环直到有人喊停 */ public class LoopUntilCommandForString { private static final String YES = "yes"; private static final String NO = "no"; private String stop = NO; /** * 循环直到有人喊停 */ public void loop() { System.out.println("Loop started"); while (stop == NO) { ; } …

例示:volatile是否只适用于primitve type ? Read More »

JMM: 断点调试可能使不可见的变量变成可见

如果一个变量没有使用volatile标识,则可能存在跨线程可见性问题; 但经验发现,断点调试时,这个可见性问题可能会消失。 比如, package player.kent.chen.learn.hivolatile; /** * 循环直到有人喊停 */ public class LoopUntilCommandForBoolBean { private BoolBean bean = new BoolBean(false); /** * 循环直到有人喊停 */ public void loop() { System.out.println("loop starts"); while (!bean.isStop()) { ; } System.out.println("Stopped because somebody said so"); } /** * 喊停 */ public void sayStop() { bean.setStop(true); System.out.println("Stop said"); } public static void main(String[] …

JMM: 断点调试可能使不可见的变量变成可见 Read More »

CAS操作中的ABA问题及Java中的解决办法

一般的CAS在决定是否要修改某个变量时,会判断一下当前值跟旧值是否相等。如果相等,则认为变量未被其他线程修改,可以改。 但是,“相等”并不真的意味着“未被修改”。 另一个线程可能会把变量的值从A改成B,又从B改回成A。 这就是ABA问题。 很多情况下,ABA问题不会影响你的业务逻辑因此可以忽略。但有时不能忽略,这时要解决这个问题,一般的做法是给变量关联一个只能递增、不能递减的版本号。在compare时不但compare变量值,还要再compare一下版本号。 Java里的AtomicStampedReference 类就是干这个的。

volatile不会被直接编译成特殊的jvm指令

volatile不会被直接编译成特殊的jvm指令; 相反,它只是存在于bytecode中作为变量的属性。到运行时,JVM才根据这个属性来决定如何生成对应的汇编指令。比如说,看到这个属性就禁止指令重排

寄存器对JVM指令来说是不可见的

JVM的指令集不会直接使用寄存器作为操作数,也就是说JVM指令看不到寄存器。 java中的volatile也跟寄存器无关,每个线程保留的变量副本不是在寄存器里,而是在JMM定义的“工作内存”里。这个内存并非寄存器。 当然JVM在运行时可以把某些内存映射到寄存器,寄存器的存取速度比内存要快得多,所以这样可以提高一点性能。 但不管怎么样,这只是运行时的优化,就JVM指令模型本身而言,它是看不到寄存器的。

JVM指令重排的例子

package player.kent.chen.learn.reorder; import java.text.MessageFormat; //转账类 public class Transfer { private int amountA = 100; private int amountB = 100; private volatile boolean committed; //转账动作 public void doTransfer() { amountA = amountA – 50; amountB = amountB + 50; committed = true; } //转账结束时打印两个账户的值 public void printAccountsWhenDone() { if(!committed) { //转账未结束则等待。 return; } System.out.println(MessageFormat.format(“amountA = {0}, …

JVM指令重排的例子 Read More »