sync&volatile

package com.hjx.thread;

import java.util.concurrent.TimeUnit;
import org.junit.Test;

public class ForSync {

  /**
   * synchronized,可重入锁,一个同步方法可以调另一个方法
   * synchronized的底层实现
   * synchronized(object)如果这个对象是静态的,那么是不是跟synchronized(T.class)一样的?
   * 锁升级:当第一个线程进入同步方法的时候,是不加锁的,就是偏向锁;如果有线程争抢,就升级为自旋锁,
   * 自旋锁:自旋10次,就相当于一个while(true),这个线程一直在自旋,10次过后还拿不到锁,升级为重量级锁
   * 重量级锁:去操作系统申请资源,处于阻塞状态
   * 自旋锁做了什么?
   * 自旋锁就是让线程处于自旋状态,不放弃cpu的时间片,多次尝试获取锁;而非自旋锁,就直接让线程处于休眠状态,等待锁释放,在唤醒线程,这样会耗费资源,代价大
   * Atomic和lock都用自旋锁,在用户态,占cpu
   * 执行时间短,枷锁代码,线程数少用自旋锁,反之用系统锁
   * */

  /**
   * volatile 保证线程可见性: 1.每个线程有自己的工作空间,还有共享内存,比如堆内存 2.利用了cpu的缓存一致性原理,volatile保证工作空间变量的更改更新到共享内存对其他线程保持可见
   */
  volatile boolean running = true;

  @Test
  public void visibility() {
    ForSync sync = new ForSync();
    new Thread(sync::m, "t1").start();
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    sync.running = false;
  }

  public void m() {
    System.out.println("start");
    while (running) {
    }
    System.out.println("end");
  }

  /**
   * 2. 禁止指令重排序: 单例模式双重检验锁 比如 :new一个对象,分为申请内存空间,初始化,再将值赋值给引用
   */

  public static volatile ForSync forSync;

 volatile int count = 0;

  public static ForSync getForSync() {
    if (forSync == null) {
      synchronized (ForSync.class) {
        if (forSync == null) {
          forSync = new ForSync();
        }
      }
    }
    return forSync;
  }

  @Test
  public void Reorder() {
    for (int i = 0; i < 100; i++) {
      count++;
      new Thread(new Runnable() {
        @Override
        public void run() {
          System.out
              .println(Thread.currentThread().getName() + "---" + ForSync.getForSync().hashCode());
        }
      }).start();
    }
    System.out.println(count);
  }

  /**
   * 3. volatile不能保证原子性 count是可见的,但count++不是原子性的,比如count由0变为1,这时其它几个线程都能读到1,都在1的基础上++ 所以不能保证线程安全
   */
  volatile int value = 0;
  void t() {
    for (int i = 0; i < 100; i++) {
      value++;
    }
  }

  @Test
  public void atomic() {
    ForSync forSync = new ForSync();
    for (int i = 0; i < 10; i++) {
      new Thread(forSync::t,"t"+i).start();
    }
    System.out.println(forSync.value);
  }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值