JAVA锁机制(上)
在实际开发中经常会用到多线程协作来处理问题,锁是处理线程安全不可缺少的机制。在JAVA中可以通过至少三种方式来实现线程锁。
1. synchronized修饰符,这种锁机制是虚拟机实现的一种锁。
2. Lock接口的实现类,这种是JAVA程序实现的锁机制。
3. CAS 通过调用底层本地方法CompareAndSet 来实现。
余下内容将结合具体的例子来看看这三种锁机制的不通,以及介绍锁实现原理。
锁机制实现介绍
在实际业务中,我们为了提高cpu的使用效率,为了提高程序执行效率,引入了多线程,而对于一些共享资源,多线程操作往往会造成线程安全问题,这时候我们往往需要一种机制可以保证多线程访问这些共享资源的时候可以先后访问。锁解决的就是这个问题。我们在访问这些资源时候需要先拿到锁,当访问介绍的时候需要释放锁,拿到锁后,其它线程就阻塞等待,一次保重共享资源多线程访问的安全。
synchronized修饰符
在虚拟机中有方法栈,对象通过堆形式存储,所有对象可以被多线程共享,synchronized是JAVA虚拟机提供的一种锁机制实现,分方法锁,对象锁,类锁,由于是虚拟机底层实现的锁机制,所以通过synchronized实现的锁机制要比程序自己实现的锁机制更加高效和方便使用。
方法锁:
1. 未加线程
public class SynchronizedMtdTest {
public static void main(String[] args) {
System.out.println("主线程开始~");
StringBuffer stringBuffer =new StringBuffer();
new Thread(new Runnable() {
@Override
public void run() {
SynchronizedMtdTest.mtd("pid="+ Thread.currentThread().getId()+",这是一个线程调用方法执行~",stringBuffer);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
SynchronizedMtdTest.mtd("pid="+ Thread.currentThread().getId()+",这是一个线程调用方法执行~",stringBuffer);
}
}).start();
System.out.println("主线程结束~");
}
public static synchronized void mtd(String text,StringBuffer stringBuffer){
try {
stringBuffer.append(text);
Thread.sleep(5000);
stringBuffer.append("\n");
System.out.println(stringBuffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
主线程开始~
主线程结束~
pid=10,这是一个线程调用方法执行~pid=11,这是一个线程调用方法执行~
pid=10,这是一个线程调用方法执行~pid=11,这是一个线程调用方法执行~
2. 加锁
public static synchronized void mtd(String text,StringBuffer stringBuffer){
try {
stringBuffer.append(text);
Thread.sleep(5000);
stringBuffer.append("\n");
System.out.println(stringBuffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
结果:
主线程开始~
主线程结束~
pid=10,这是一个线程调用方法执行~
pid=10,这是一个线程调用方法执行~
pid=11,这是一个线程调用方法执行~
可见在没有加锁的情况下结果是乱的,而且每次执行的循序可能不一样,而加锁后从执行结果可以看出对对象的操作是互斥操作,保证了线程的安全。
对象锁
对于方法锁保证了多线程在调用方法时候互斥,而实际中我们方法中不仅有对共享对象操作还有局部对象的操作,未了提高程序的执行效率,JAVA提供了对象锁和类锁实现。
public static void mtd(String text, StringBuffer stringBuffer) {
System.out.println("方法调用开始~");
synchronized (stringBuffer) {
stringBuffer.append(text);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stringBuffer.append("\n");
System.out.println(stringBuffer);
}
System.out.println("方法调用结束~"); }
结果:
方法调用开始~
方法调用开始~
主线程结束~
pid=10,这是一个线程调用方法执行~
方法调用结束~
pid=10,这是一个线程调用方法执行~
pid=11,这是一个线程调用方法执行~
方法调用结束~
可以看到被加锁的对象在多线程访问的时候,互斥访问。
假定猜想
对象锁是保证锁内代码执行互斥?还是只保证对加锁对象做的互斥。做如下调整
public static void mtd(String text, StringBuffer stringBuffer) {
System.out.println("方法调用开始~");
synchronized (stringBuffer) {
System.out.println("-----------1--------");
stringBuffer.append(text);
System.out.println("-----------2--------");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stringBuffer.append("\n");
System.out.println(stringBuffer);
}
System.out.println("方法调用结束~");
}
结果:
主线程开始~
方法调用开始~
-----------1--------
-----------2--------
主线程结束~
方法调用开始~
pid=10,这是一个线程调用方法执行~
方法调用结束~
-----------1--------
-----------2--------
pid=10,这是一个线程调用方法执行~
pid=11,这是一个线程调用方法执行~
方法调用结束~
类锁
public static void appendStr(String text) {
synchronized (Object.class) {
stringBuffer.append(text);
try {
System.out.println("-------------");
System.out.println(stringBuffer);
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printStr() {
synchronized (Object.class) {
System.out.println("-------------");
System.out.println(stringBuffer);
}
}
}
可见:
对于对象锁来说,可以理解为在内存有个记录锁机制的地方,所有可以共享这个空间的线程,都可以获取锁和释放锁,而且相同线程可以重复获取锁,但是其它线程在未获得锁的时候需要阻塞等待。而类锁,原理相同,不过可能存放区域不同。
JAVA锁机制(上)的更多相关文章
- 转 : 深入解析Java锁机制
深入解析Java锁机制 https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw%3D%3D&mid=2247485524&idx=1&s ...
- Java 锁机制总结
锁的种类 独享锁 VS 共享锁 独享锁:锁只能被一个线程持有(synchronized) 共享锁:锁可以被多个程序所持有(读写锁) 乐观锁 VS 悲观锁 乐观锁:每次去拿数据的时候都乐观地认为别人不会 ...
- Java锁机制深入理解
Java锁机制 背景知识 指令流水线 CPU的基本工作是执行存储的指令序列,即程序.程序的执行过程实际上是不断地取出指令.分析指令.执行指令的过程. 几乎所有的冯•诺伊曼型计算机的CPU,其工 ...
- java锁机制的面试题
java锁机制的面试题 1.ABA问题 2.CAS乐观锁 3.synchronize实现原理 4.synchronize与lock的区别 5.volatile实现原理 6.乐观锁的业务场景及实现方式 ...
- java锁机制
2.4 锁机制 临界区是指,使用同一个锁控制的同一段代码区或多段代码区之间,在同一时间内最多只能有一个线程在执行操作.这个概念与传统的临界区有略微的差别,这里不想强调这些概念上的差别,临 ...
- Java锁机制了解一下
前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 只有光头才能变强! 本文章主要讲的是Java多线程加锁机制,有两种: Synchro ...
- JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,
如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...
- java 锁机制(synchronized 与 Lock)
在java中,解决同步问题,很多时候都会使用到synchronized和Lock,这两者都是在多线程并发时候常使用的锁机制. synchronized是java中的一个关键字,也就是说是java内置的 ...
- 【面试专栏】JAVA锁机制
1. 悲观锁 / 乐观锁 在Java和数据库中都存在悲观锁和乐观锁的应用.Mysql锁机制中的悲观锁和乐观锁请查看: Mysql锁机制--悲观锁和乐观锁 悲观锁:在获得数据时先加锁,只到数 ...
随机推荐
- pandas将字段中的字符类型转化为时间类型,并设置为索引
假设目前已经引入了 pandas,同时也拥有 pandas 的 DataFrame 类型数据. import pandas as pd 数据集如下 df.head(3) date open close ...
- Spring MVC 框架学习
一.spirng的简介 Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情. ...
- T-SQL创建作业
/*1.--创建作业 */ /*--调用示例 --每月执行的作业 exec p_createjob @jobname='mm',@sql='select * from syscolumns',@fre ...
- Feed系统架构资料收集(转)
add by zhj:有些链接已经失效,后续会修改. 原文:http://blog.csdn.net/zhangzhaokun/article/details/7834797 完全用nosql轻松打造 ...
- 【Python】读取各种文档(txt、csv、excel、pdf)方法
1.读取txt文件 注意事项: 1..txt文件同下方脚本所在的.py文件需要在同一个文件夹下 # coding=utf-8 txt读取 with open("1233.txt") ...
- 使用Rxjava自己创建RxBus
https://piercezaifman.com/how-to-make-an-event-bus-with-rxjava-and-rxandroid/ https://lingyunzhu.git ...
- OPENSSL编程 (secure shell, ssh)
很好的 OPENSSL编程 教程,名字就叫“OPENSSL编程” 它里面还有很多关于密码学的东西. http://www.pengshuo.me http://www.pengshuo.me/2014 ...
- hive两大表关联优化试验
呼叫结果(call_result)与销售历史(sale_history)的join优化: CALL_RESULT: 32亿条/444G SALE_HISTORY:17亿条/439G 原逻辑 Map: ...
- C#使用Gzip解压缩完整读取网页内容
using System; using System.Threading; using System.Text; using System.Text.RegularExpressions; using ...
- httpclient接口测试完整用例以及获取信息的方法
原文地址https://blog.csdn.net/fhaohaizi/article/details/78088075 原文地址https://blog.csdn.net/fhaohaizi/art ...