synchronized(隐士锁,内置锁)
synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成…)
/**
* synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成....)
*/
public class GpsEngine {
private static GpsEngine gpsEngine;
//单例
private static GpsEngine getInstance(){
if(gpsEngine == null){
//Thread-0 CPU执行权被操作系统调度给释放[暂停] [获得了cpu执行权 回复] 继续往下走
gpsEngine = new GpsEngine(); //Thread-1 CPU执行了一次 new ;new 了两次就不是单例了 安全性问题
}
return gpsEngine;
}
//如果多个线程 或者多个地方调用
//多线程执行的时候 需要非常注意 安全性问题
}
/**
* synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成....)
*/
public class GpsEngine {
private static GpsEngine gpsEngine;
//单例
private static synchronized GpsEngine getInstance2(){
if(gpsEngine == null){
//Thread-0 此时Thread-1进不来
gpsEngine = new GpsEngine();
}
return gpsEngine;
}//Thread-0执行完毕
}
类锁:
static synchronized (静态+synchronized 所持有的锁就是这个引擎GpsEngine 的class)
静态代表还没new出来还没有实例化之前就会通过class的方式加载
持有一把锁 GpsEngine.class对象锁 == 类锁
上述代码效率太低,改进一下:
//双重检测 比较典型的单例
//双重检测 比较典型的单例
public static GpsEngine getGpsEngine() {
if(gpsEngine == null){
//Thread-0,Thread-1,Thread-2,Thread-3....都进的来
//GpsEngine.class对象锁 == 类锁
synchronized (GpsEngine.class){
//Thread-0, 此时 Thread-1,Thread-2,Thread-3....进不来
if(gpsEngine == null){
gpsEngine = new GpsEngine();
}
}
}
return gpsEngine;
}
对象锁
//多线程执行中,基本上有安全性问题
//加锁
public class SynTest {
private long count = 0;
//累加函数
public void incCount() {
count ++;
}
//线程
private static class Count extends Thread {
private SynTest simplOpen;
public Count(SynTest simplOpen){
this.simplOpen = simplOpen;}
@Override
public void run() {
for(int i = 0; i<10000; i++) {
simplOpen.incCount();// count = count + 10000
}
}
}
public static void main(String[] args) throws InterruptedException {
SynTest synTest = new SynTest();
//启动两个线程
Count count1 = new Count(synTest);
Count count2 = new Count(synTest);
count1.start();
count2.start();
Thread.sleep(50);
System.out.println(synTest.count);//20000
}
}
14760 //第一次结果
18538 //第二次结果
14289 //第三次结果
加上对象锁:
//累加函数
//synchronized == 对象锁 持有一把锁 SynTest.this SynTest的实例
public synchronized void incCount() {
count ++;
}
20000
public void incCount2(){
synchronized (this) {
//自己去寻找
count ++;
}
}
public void incCount2(){
synchronized (SynTest.this) {
//自己去寻找
count ++;
}
}
20000
//随便持有一把锁, 对象锁 Object对象
private Object object = new Object();
private String str = new String();
public void incCount3(){
synchronized (object) {
//自己去寻找
count ++;
}
}
显示锁
可重入锁 ReentrantLock()
synchronized 天生也是可重入锁
可重入锁就是在递归的时候可反复的拿锁
// synchronized 天生是可重入锁
//如果synchronized不是可重入锁,无法调用自己 递归第二次第N次无法拿到锁 造成卡死状态一样
public synchronized void add(){
count ++;
add();
}
ReentrantLock()
//syn 隐士的 内部会完成 锁定 解锁 等等 底层逻辑 我们改不了 看不到,只需要加一个关键字
//Lock 显示锁 我们程序员可以控制 锁定 解锁 等逻辑
public class LockDemo {
private int count = 0;
//synchronized 天生也是可重入锁
//可重入锁 ReentrantLock()
private Lock lock = new ReentrantLock();
//多线程执行,如果不加锁,一定存在安全问题
public void incr() {
lock.lock(); // 开发者自己锁定
count ++; //如果发生异常,后面的无法被解锁别的线程就永远进不来了
lock.unlock();// 开发者自己去解锁
}
public void incr2() {
lock.lock(); // 开发者自己锁定
try{
count ++;
}finally {
//一定会执行finally里面的语句,一定会解锁
lock.unlock();// 开发者自己去解锁
}
}
// synchronized 天生是可重入锁
//如果synchronized不是可重入锁,无法调用自己 递归第二次第N次无法拿到锁 造成卡死状态一样
public synchronized void add(){
count ++;
add();
}
public static void main(String[] args){
}
}