代码很简单
public class CompareAndSet {
public static void main(String [] args){
Threadmin th = new Threadmin();
new Thread(th, "1号窗口").start();
new Thread(th, "2号窗口").start();
new Thread(th, "3号窗口").start();
new Thread(th, "4号窗口").start();
}}public class Threadmin implements Runnable{
AtomicInteger counter = new AtomicInteger(50);
volatile int result = counter.get();
boolean flag;
public void run() {
while(result>0){
System.out.println("result:"+result) ;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flag = counter.compareAndSet(result, result - 1);
if(flag) {
result = counter.decrementAndGet();
System.out.println("result:"+result+":"+Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票");
}else{
System.out.println("flag:"+flag);
System.out.println(Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票*");
}
}
}打印的结果
result:50
result:50
result:50
result:50
result:48:3号窗口卖出 第 2张票
result:48
result:46:4号窗口卖出 第 4张票
result:46
result:44:2号窗口卖出 第 6张票
result:44
result:42:1号窗口卖出 第 8张票
result:42
result:40:4号窗口卖出 第 10张票
result:38:3号窗口卖出 第 12张票
result:38
result:38
result:36:2号窗口卖出 第 14张票
result:36
result:34:1号窗口卖出 第 16张票
result:34
result:32:3号窗口卖出 第 18张票
result:28
result:28:2号窗口卖出 第 22张票
result:28
result:30:4号窗口卖出 第 20张票
result:28
result:26:1号窗口卖出 第 24张票
result:26
result:24:3号窗口卖出 第 26张票
result:24
result:22:1号窗口卖出 第 28张票
result:22
result:20:2号窗口卖出 第 30张票
result:20
result:18:4号窗口卖出 第 32张票
result:18
result:16:3号窗口卖出 第 34张票
result:14
result:14:2号窗口卖出 第 36张票
result:12:1号窗口卖出 第 38张票
result:12
result:12
result:10:4号窗口卖出 第 40张票
result:10
result:8:1号窗口卖出 第 42张票
result:8
result:6:2号窗口卖出 第 44张票
result:6
result:4:4号窗口卖出 第 46张票
result:4
result:2:3号窗口卖出 第 48张票
result:2
result:0:1号窗口卖出 第 50张票
result:-2:2号窗口卖出 第 52张票
result:-4:4号窗口卖出 第 54张票
result:-6:3号窗口卖出 第 56张票
为什么出负数了
public class CompareAndSet {
public static void main(String [] args){
Threadmin th = new Threadmin();
new Thread(th, "1号窗口").start();
new Thread(th, "2号窗口").start();
new Thread(th, "3号窗口").start();
new Thread(th, "4号窗口").start();
}}public class Threadmin implements Runnable{
AtomicInteger counter = new AtomicInteger(50);
volatile int result = counter.get();
boolean flag;
public void run() {
while(result>0){
System.out.println("result:"+result) ;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flag = counter.compareAndSet(result, result - 1);
if(flag) {
result = counter.decrementAndGet();
System.out.println("result:"+result+":"+Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票");
}else{
System.out.println("flag:"+flag);
System.out.println(Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票*");
}
}
}打印的结果
result:50
result:50
result:50
result:50
result:48:3号窗口卖出 第 2张票
result:48
result:46:4号窗口卖出 第 4张票
result:46
result:44:2号窗口卖出 第 6张票
result:44
result:42:1号窗口卖出 第 8张票
result:42
result:40:4号窗口卖出 第 10张票
result:38:3号窗口卖出 第 12张票
result:38
result:38
result:36:2号窗口卖出 第 14张票
result:36
result:34:1号窗口卖出 第 16张票
result:34
result:32:3号窗口卖出 第 18张票
result:28
result:28:2号窗口卖出 第 22张票
result:28
result:30:4号窗口卖出 第 20张票
result:28
result:26:1号窗口卖出 第 24张票
result:26
result:24:3号窗口卖出 第 26张票
result:24
result:22:1号窗口卖出 第 28张票
result:22
result:20:2号窗口卖出 第 30张票
result:20
result:18:4号窗口卖出 第 32张票
result:18
result:16:3号窗口卖出 第 34张票
result:14
result:14:2号窗口卖出 第 36张票
result:12:1号窗口卖出 第 38张票
result:12
result:12
result:10:4号窗口卖出 第 40张票
result:10
result:8:1号窗口卖出 第 42张票
result:8
result:6:2号窗口卖出 第 44张票
result:6
result:4:4号窗口卖出 第 46张票
result:4
result:2:3号窗口卖出 第 48张票
result:2
result:0:1号窗口卖出 第 50张票
result:-2:2号窗口卖出 第 52张票
result:-4:4号窗口卖出 第 54张票
result:-6:3号窗口卖出 第 56张票
为什么出负数了
减成负的了呗
不是result小于0 就应该停止了吗
这足够你4个线程都通过while(result>0)这个判断了
而你的result的递减是在你打印之前处理的
所以你会打印出在最后一次result>0之后,被递减了4次的结果
result = counter.decrementAndGet();
System.out.println("result:"+result+":"+Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票");
这两句话的位置,可以少打印出一条负的数据
虽然你用的是primary类型,但存在这种情况:在你通过primary的值去判断一个条件式后,再次对primary进行修改操作之前,有别的线程闯进啦,修改了primary。这样就很容易出现你不想要的结果了。
下面是我从javaeye考的一个例子,对你应该有启发的:volatile运算存在脏数据问题
volatile仅仅能保证变量可见性, 无法保证原子性.
volatile的race condition示例:
Java代码
public class TestRaceCondition {
private volatile int i = 0;
public void increase() {
i++;
}
public int getValue() {
return i;
}
}
当多线程执行increase方法时, 是否能保证它的值会是线性递增的呢?
答案是否定的.
原因:
这里的increase方法, 执行的操作是i++, 即 i = i + 1;
针对i = i + 1, 在多线程中的运算, 本身需要改变i的值.
如果, 在i已从内存中取到最新值, 但未与1进行运算, 此时其他线程已数次将运算结果赋值给i.
则当前线程结束时, 之前的数次运算结果都将被覆盖.
即, 执行100次increase, 可能结果是 < 100.
一般来说, 这种情况需要较高的压力与并发情况下, 才会出现.
那这么说 我没有实现AtomicInteger线程同步了? 那这个代码如何改呢
1)同步,这种方法先不考虑
2)采用原子操作,让条件检查与修改变量“粘”在一起,不给其他线程机会:import java.util.concurrent.atomic.AtomicInteger;public class Threadmin implements Runnable { AtomicInteger counter = new AtomicInteger(50); public void run() {
while (true) {
int result = counter.getAndDecrement();
if (result <= 0)
break; System.out.println("result:" + result);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("result:" + result + ":" + Thread.currentThread().getName() + "卖出 第 " + (50 - result)
+ "张票");
}
} public static void main(String[] args) {
Threadmin th = new Threadmin();
new Thread(th, "1号窗口").start();
new Thread(th, "2号窗口").start();
new Thread(th, "3号窗口").start();
new Thread(th, "4号窗口").start();
}
}