代码很简单
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张票

为什么出负数了

解决方案 »

  1.   

    你的result不是一直在减么……
    减成负的了呗
      

  2.   

    但是我 while (result>0)
    不是result小于0 就应该停止了吗
      

  3.   

    但是你在while(result>0) 之后sleep了100ms
    这足够你4个线程都通过while(result>0)这个判断了
    而你的result的递减是在你打印之前处理的
    所以你会打印出在最后一次result>0之后,被递减了4次的结果
      

  4.   

    如果你交换
    result = counter.decrementAndGet();
    System.out.println("result:"+result+":"+Thread.currentThread().getName() + "卖出 第 "+ (50 - result )+"张票");
    这两句话的位置,可以少打印出一条负的数据
      

  5.   

    当result值逼近临近值0时,多个线程同时检测到while(result>0)条件,同时进入循环修改了result和counter。
    虽然你用的是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.
    一般来说, 这种情况需要较高的压力与并发情况下, 才会出现. 
      

  6.   

    谢谢你 的回答
    那这么说 我没有实现AtomicInteger线程同步了? 那这个代码如何改呢
      

  7.   

    你代码核心问题是比较和修改变量的值不是“粘”在一起的,中间给其他线程提供了闯入的机会。有两种解决办法:
    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();
        }
    }