原子性的测试——T2320

package 对象及变量的并发访问2;

import 多线程技能1.Test;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 *  原子性的测试
 *  在32位系统中,针对未使用volatile声明的long或double数据类型没有实现写原子性。
 *如果要实现,则声明变量时添加volatile。在64位操作系统中,原子性取决于具体的实现,
 *在X86架构64位JDK中,写double和long是原子的。
 *   另外,volatile关键最致命的缺点是不支持原子性,也就是多个线程对用volatile修饰的
 *变量i执行i++操作时,i++操作还会被分为3步,造成非线程安全问题。
 *
 *   在32位中,i既不是1也不是-1 而是4294967295
 */

class MyServiceT2320{
    public long i;
}

class MyThreadAT2320 extends Thread{
    private MyServiceT2320 serviceT2320;
    public  MyThreadAT2320(MyServiceT2320 serviceT2320){
        super();
        this.serviceT2320=serviceT2320;
    }

    @Override
    public void run() {
        while (true){
            serviceT2320.i=1;
        }
    }
}

class MyThreadBT2320 extends Thread{
    private  MyServiceT2320 serviceT2320;

    public MyThreadBT2320(MyServiceT2320 myServiceT2320){
        super();
        this.serviceT2320=myServiceT2320;
    }

    @Override
    public void run() {
        while (true){
            serviceT2320.i=-1;
        }
    }
}

class TestT2320{
    public TestT2320() throws InterruptedException {
        MyServiceT2320 myServiceT2320=new MyServiceT2320();
        MyThreadAT2320 at2320=new MyThreadAT2320(myServiceT2320);
        MyThreadBT2320 bt2320=new MyThreadBT2320(myServiceT2320);

        at2320.start();
        bt2320.start();

        Thread.sleep(1000);

        System.out.println("long i 二进制是:"+Long.toBinaryString(1));
        System.out.println("long -1 二进制是:"+Long.toBinaryString(-1));

        while (true){
            long getValue=myServiceT2320.i;
            if(getValue!=1&&getValue!=-1){
                System.out.println("i的值是:"+Long.toBinaryString(getValue)+"十进制是:"+getValue);
                System.exit(0);
            }
        }
    }
}

/**
 *   2.使用volatile解决在32位系统中long和double数据类型写操作为非原子性。
 *
 */

class MyService2T2320{
    volatile public long i ;
}

class MyThreadA2T2320 extends Thread{
    private  MyService2T2320 service2T2320;

    public MyThreadA2T2320(MyService2T2320 service2T2320){
        super();
        this.service2T2320=service2T2320;
    }

    @Override
    public void run() {
        service2T2320.i=1;
    }
}

class MyThreadB2T2320 extends Thread{
    private  MyService2T2320 service2T2320;

    public MyThreadB2T2320(MyService2T2320 service2T2320){
        super();
        this.service2T2320=service2T2320;
    }

    @Override
    public void run() {
        service2T2320.i=-1;
    }
}

class Test2T2320{
    public Test2T2320() throws InterruptedException {
        MyService2T2320 myService2T2320=new MyService2T2320();

        MyThreadA2T2320 a2T2320=new MyThreadA2T2320(myService2T2320);
        MyThreadB2T2320 b2T2320=new MyThreadB2T2320(myService2T2320);

        a2T2320.start();
        b2T2320.start();

        Thread.sleep(1000);

        System.out.println("long i 二进制是:"+Long.toBinaryString(1));
        System.out.println("long -1 二进制是:"+Long.toBinaryString(-1));

        while (true){
            long getValue=myService2T2320.i;
            if(getValue!=1&&getValue!=-1){
                System.out.println("i的值是:"+Long.toBinaryString(getValue)+"十进制是:"+getValue);
                System.exit(0);
            }
        }
    }
}

/**
 *  3.关键字volatile int i++非原子的特性
 *    使用多线程执行volatile int i++赋值操作时为非原子的。
 *
 *   结果并不是1000;说明count++是非原子的。 更改MyThread类
 *
 *   如果方法private static void addCount()前加入synchronized同步关键字,那么就没必要
 *再使用volatile关键字来声明count变量。
 *   关键字volatile使用的主要场合是在多线程中可以感知实例变量被更改了,并且可以获得最新的值,也就是
 * 可以用于增加可见性/可视性
 *   关键字volatile提示线程每次从共享内存中去读取变量,而不是从私有内存中去读取,这样就保证了同步数
 *据的可见性。但如果修改实例数据变量,如i++,并不是一个原子性操作,i++分为以下三步
 * 1)从内存中读取i的值
 * 2)计算i的值
 * 3)将i写入内存
 *  如果在第二步时,有多个线程操作,修改i的值,那么这个时候就会出现脏数据,解决办法是使用synchronize
 *  d关键字。volatile本身并不处理int i++这个操作。
 */

class MyThread3T2320 extends Thread{
    volatile public  static int count;

    private static void addCount(){
        for (int i=0;i<100;i++){
            count++;
        }
        System.out.println("count="+count);
    }

    @Override
    public void run() {
        addCount();
    }
}

class MyThread32T2320 extends Thread{
    volatile public static int count;
    /**
     * 加static关键字——>synchronized与static锁的内容就是MyThread32T2320.class类——>达到同步效果
     */
    synchronized private static void addCount(){
        for(int i=0;i<100;i++){
            count++;
        }
        System.out.println("count="+count);
    }

    @Override
    public void run() {
        addCount();
    }
}

class Run3T2320{
    public Run3T2320(){
        MyThread3T2320 [] myThread3T2320s=new MyThread3T2320[100];
        for (int i=0;i<100;i++){
            myThread3T2320s[i]=new MyThread3T2320();
        }

        for(int i=0;i<100;i++){
            myThread3T2320s[i].start();
        }
    }
}
class Run32T2320{
    public Run32T2320 (){
        MyThread32T2320 [] myThread32T2320s=new MyThread32T2320[100];
        for (int i=0;i<100;i++){
            myThread32T2320s[i]=new MyThread32T2320();
        }

        for (int i=0;i<100;i++){
            myThread32T2320s[i].start();
        }
    }
}

/**
 *   4.使用Atomic原子进行i++操作实现原子性
 *    除了在i++操作时使用synchronized关键字实现同步外,还可以使用AtomicInteger原子实现原子性
 *    原子操作是不可分割的整体,没有其他线程能够中断或检查处于原子操作中的变量,一个原子(atomic)
 * 类型就是一个原子操作可以类型,它可以没有锁的情况下做到线程安全
 */
class addCountThreadT2320 extends Thread{
    private AtomicInteger count=new AtomicInteger(0);

    @Override
    public void run() {
        for (int i=0;i<10000;i++){
            System.out.println(count.incrementAndGet());
        }
    }
}

class Run4T2320{
    public Run4T2320(){
        addCountThreadT2320 countThreadT2320=new addCountThreadT2320();

        Thread thread=new Thread(countThreadT2320);
        thread.start();

        Thread thread1=new Thread(countThreadT2320);
        thread1.start();

        Thread thread2=new Thread(countThreadT2320);
        thread2.start();

        Thread thread3=new Thread(countThreadT2320);
        thread3.start();

        Thread thread4=new Thread(countThreadT2320);
        thread4.start();
    }
}

/**
 *   5.出现逻辑混乱与解决。
 *    在有逻辑的情况下,原子类的输出结果具有随机性。
 */

class MyService5T2320{
    public static AtomicLong aiRef=new AtomicLong();

    public synchronized void addNum(){
        System.out.println(Thread.currentThread().getName()+"100后"+aiRef.addAndGet(100));
        aiRef.addAndGet(1);
    }
}

class MyThread5T2320 extends Thread{
    private MyService5T2320 service5T2320;

    public MyThread5T2320(MyService5T2320 service5T2320){
        super();
        this.service5T2320=service5T2320;
    }

    @Override
    public void run() {
        service5T2320.addNum();
    }
}

class Run5T2320{
    public Run5T2320(){
        try {
            MyService5T2320 service5T2320=new MyService5T2320();

            MyThread5T2320 [] myThread5T2320s=new MyThread5T2320[5];
            for (int i=0;i<myThread5T2320s.length;i++){
                myThread5T2320s[i]=new MyThread5T2320(service5T2320);
            }

            for (int i=0;i<myThread5T2320s.length;i++){
                myThread5T2320s[i].start();
            }

            Thread.sleep(1000);
            System.out.println(MyService5T2320.aiRef.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class T2320 {
    public static void main(String[] args) throws InterruptedException {
        //TestT2320 testT2320=new TestT2320();

        //Test2T2320 test2T2320=new Test2T2320();

       // Run3T2320 run3T2320=new Run3T2320();

        //Run32T2320 run32T2320=new Run32T2320();

        //Run4T2320 run4T2320=new Run4T2320();

        Run5T2320 run5T2320=new Run5T2320();

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值