Java Thread 多线程的 锁 synchronized volatile

synchronized

1. 锁的是对象
2. 非静态 锁的是this   静态 锁的是 XX.class
3. 锁定方法 与 非锁定方法可以同时执行
4. 锁升级 
	 - synchronized锁 可重入
	 - 执行时间短(加锁代理), 
	 - 线程数少, 用自旋
	 - 执行时间长,线程数多,用系统锁
1加锁的方式:
public class T { 
	
	private Object o = new Object();	//	锁
	private int count = 10;
	
	public void m() {
		synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁
			count--;
			System.out.println(Thread.currentThread().getName() + " count = " + count);
		}
	}
}
2.加锁的方式:
public class T {
	
	private int count = 10;
	
	public void m() {
		synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁
			count--;
			System.out.println(Thread.currentThread().getName() + " count = " + count);
		}
	}
}
3.加锁的方式:
public class T {

	private int count = 10;
	
	public synchronized void m() { //等同于在方法的代码执行时要synchronized(this)
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}
}
4.静态加锁的方式:
public class T {

	private static int count = 10;
	
	public synchronized static void m() { //这里等同于synchronized(FineCoarseLock.class)
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}
	
	public static void mm() {
		synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
			count --;
		}
	}
}
Demo:
public class T implements Runnable {

	private int count = 10;

	public synchronized void run() {
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}

	public static void main(String[] args) {

		for(int i=0; i<5; i++) {
			T t = new T();
			new Thread(t, "THREAD" + i).start();
		}
	}
}

volatile

1. 保证线程可见性 
		- MESI
		- 缓存一致性协议
2. 禁止指令重排序
		- DCL单例
		- Double Check Lock
		- Mgr06.java
		- loadfence 原语指令
		- storefence 原语指令

单例 设计模式
饿汉式

/**
 * 饿汉式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用!
 * 唯一缺点:不管用到与否,类装载时就完成实例化
 */
 
//	饿汉式方式一
public class Hungry01 {
    private static final Hungry01 INSTANCE = new Hungry01();

    private Hungry01() {};

    public static Hungry01 getInstance() {
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

    public static void main(String[] args) {
        Hungry01 m1 = Hungry01.getInstance();
        Hungry01 m2 = Hungry01.getInstance();
        System.out.println(m1 == m2);
    }
}

//	饿汉式方二
public class Hungry02 {
    private static final Hungry02 INSTANCE;
    static {
        INSTANCE = new Hungry02();
    }

    private Hungry02() {};

    public static Hungry02 getInstance() {
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

    public static void main(String[] args) {
        Hungry02 m1 = Hungry02.getInstance();
        Hungry02 m2 = Hungry02.getInstance();
        System.out.println(m1 == m2);
    }
}

懒汉式

/**
 * 懒汉式 lazy loading
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 * 可以通过synchronized解决,但也带来效率下降
 */
//	懒汉式 
public class lazy01 {
    private static volatile lazy01 INSTANCE; //JIT

    private lazy01() {}

    public static lazy01 getInstance() {
        if (INSTANCE == null) {
            //双重检查
            synchronized (lazy01.class) {
                if(INSTANCE == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new lazy01();
                }
            }
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
                System.out.println(lazy01.getInstance().hashCode());
            }).start();
        }
    }
}
解决同样的问题的更高效的方法,使用AtomXXX类
AtomXXX 类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的
  1. CAS (无锁优化 自旋)
    • Compare And Set/Swap
    • cas(V,Expected,NewValue) // Expected 期望值 如果一样则执行
      • if V == E
        V = New
        otherwise try again or fail
      • CPU 原语支持
  2. ABA 问题
    加 version 版本号
    A 1.0
    B 2.0
    C 3.0
    cas(version)
    基础类型 无所谓
    引用类型 注意 和女朋友复合,中间经历了别的女人
Unsafe
直接操作内存
 	allocateMemory putXX freeMemory pageSize
直接生成类实例
	allocateInstance
直接操作类或实例变量
	objectFieldOffset
	getInt
	getObject
CAS相关操作
	weakCompareAndSetObject Int Long
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值