synchronized深度解析

news/2024/5/17 15:21:46 标签: synchronized
synchronized_0">synchronized的使用
1.synchronized锁的分类
	对象锁(非静态),类锁(静态)
2.synchronized使用案例:
 * 同步普通方法:		//此时的锁对象是this
    public synchronized void method1(){

    }
 * 同步静态方法:		//此时的锁对象是当前类的Class对象
    public static synchronized void method2(){

    }
 * 同步代码块:		//此时的锁对象是this
    synchronized(this){

    }
 * 同步静态代码块: 	//此时的锁对象是当前类的Class对象
	synchronized(Demo.class){

    }
3.对象锁和类锁的区别:
* 同一个字节码文件,始终只有唯一的一个Class对象;但是却可以有多个new出来的对象实例
即: obj.getClass() == Object.class == Class.forName("java.lang.Object");
	Object obj1 = new Object(); 
	Object obj2 = new Object(); 
	obj1 != obj2 ; 
	obj1.getClass() == obj2.getClass();
4.多线程访问同步方法的7种案例:
* 两个线程访问的是一个对象的同一个同步方法
 线程安全,线程串行
* 两个线程访问的是同一个字节码文件的两个实例对象的同一个同步方法
 线程不安全,线程并行
* 两个线程访问的是synchronized的静态方法
 线程安全,线程串行
* 两个线程分别访问同步方法和非同步方法
 线程并行
* 访问同一个对象的不同的同步方法
 线程安全,线程串行
* 同时访问静态同步方法和静态非同步方法
 线程不安全,线程并行
 
5.synchronized关键字的性质
* 可重入性:线程得到对象锁之后,可以再次获得该对象锁,synchronized锁可重入性是线程级别的
	 public synchronized  void method(){
        synchronized (this){
            synchronized (this){
                synchronized (this){
                    System.out.println("hello...");
                }
            }
        }
    }
* 不可剥夺性:线程获得锁对象后,只有在方法执行完毕或者抛出异常,才会释放锁,否则其他线程不能干扰它的锁的释放

6.synchronized关键字的原理:
* 同步代码块: monitorenter指令,monitorexit指令,monitor计数器
	每一个对象的对象头中都保存有一个monitor对象(管程或监视器锁),synchronized就是依赖于monitor对象实现的;synchronized代码块会被编译为一段monitorenter,monitorexit指令;当程序执行到monitorenter指令时,线程会去尝试获取锁对象所对应的monitor持有权,如果monitor计数器为0,则当前线程获得monitor持有权,并且将monitor计数器+1,进入runnable状态;否则进入锁阻塞状态;当同步代码块执行完毕,再执行monitorexit指令,将monitor计数器-1;jvm为了保证每一个monitor最终都能回到0状态,通常一个monitorenter会对应多个monitorexit指令(比如:正常结束-1,抛异常-1);sunchronized锁中,抛出异常也会执行monitorexit指令
* 同步方法:
	同步方法是隐式同步,jvm根据方法的标志flags下的ACC_SYNCHRONIZED来分辨一个同步方法,当线程调用这个方法时,现根据ACC_SYNCHRONIZED标志判断方法是否是一个同步方法,然后尝试获取monitor对象,已经被获取了的monitor对象无法再获取,直到上一个线程释放monitor对象
	
7.synchronized锁保证内存可见性的原理:
	线程不安全情况下:主内存会为每一个线程分配一个本地内存,并且将主内存中的数据在各本地内存中保存一份副本,当多线程开始操作这个数据时,实际上各个线程操作的都是本地内存中的副本,只有最后执行完毕才会更新到主内存,因此,导致了数据不一致
	volatile保存内存可见性:volatile修饰后的数据,子线程在对数据副本进行操作前,会先从主内存中更新最新数据,操作完毕后,也会立刻将数据更新到主内存,但是一个count++的操作将不再保持原子性;因此多线程条件下,除非能保证单线程修改数据,其他线程只查询数据;否则线程不安全
	synchronized保证内存可见性:synchronized锁在获得monitor锁后,会立即将数据从主内存中更新,并且在count++这个过程中,操作原子性,最后释放monitor锁后,将数据又更新到主内存中;因此线程安全
	
8.synchronized锁注意事项:
* 锁对象不能为null,如果锁对象为null,那么对象头中就没有monitor,同步方法最终效果相当于直接跳过
* 锁的范围不宜过大,因为synchronized锁影响效率
* 注意避免死锁

9.debug: evaluate expression --> this.getState()  可以查看线程的状态

http://www.niftyadmin.cn/n/1490510.html

相关文章

redis学习-17 redis内部实现之ziplist

1、概念 ziplist是一个经过特殊编码的双向链表,它的设计目标就是为了提高存储效率。 ziplist可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的, 而不是编码成字符串序列。它能以O(1)的时间复杂度在表的两端提供push和pop…

redis学习-18 redis内部实现之内存回收

因为 C 语言并不具备自动的内存回收功能, 所以 Redis 在自己的对象系统中构建了一个引用计数(reference counting)技术实现的内存回收机制, 通过这一机制, 程序可以通过跟踪对象的引用计数信息, 在适当的时…

网络编程-bio

ClientSocket public class TestClient{public static void main(String[] args){//建议一个Socket连接Socket socket null;//通过socket连接,输出流(请求)对象,获取输入流(响应)InputStream is null;OutputStream os null;try{socket new Socket("localhost",8…

B2B2C项目部署

Zookeeper集群 1.Leader选举机制Zookeeper中的每一个节点都会监听一个投票选举的端口;每当有一个节点启动,所有已经启动的Zookeeper 都会去参与一次投票,根据节点ID大的来选择Leader,超过半数节点投票成功,则选举出Leader;后续即便有节点ID 更大的,Leader选举出来后,也不再进行…

redis学习-19 Redis为什么设计成单线程

1、问题: “假设,此刻有任务A和任务B,现在有如下两种执行方式” 方式一:两个线程,一个线程执行A,另一个线程执行B 方式二:一个线程,先执行A,执行完以后继续执行B 哪个方式执行更快&#xff…

Redis(源码剖析):---集群之集群数据结构(clusterNode、clusterLink、clusterState、CLUSTER MEET命令的实现)

一、struct clusterNode clusterNode结构保存了一个节点的当前状态,比如节点的创建时间、节点的名字、节点 当前的配置纪元、节点的IP地址和端口号等等每个节点都会使用一个clusterNode结构来记录自己的状态,并为集群中的所有其他节点(包括主…

Beego学习-01 基础篇

概述 beego是一个快速开发go应用的http框架,他可用来快速开发API、Web以及后端服务等各种应用。 beego的架构 cache 缓存模块 config 配置模块 context 上下文模块 logs 日志模块 orm 和数据库相关的操作 session httplib 和网络相关的模块 beego执行逻辑 页面…

网络编程-nio

NIO 1.BIO:Block IO,同步阻塞IO,主要应用于文件IO(stream流的方式)和网络IO(socket) 2.NIO:None-Block IO,非阻塞IO,jdk1.4提供的新特性;NIO主要有三个核心分:Selector,Channel,Buffer; 由Selector监听多个通道事件,数据从通道输出到缓冲区,或者从缓冲区输入入到通道中; 3.AIO…