java线程同步以及对象锁和类锁解析(多线程synchronized关键字)
一、关于线程安全
1.是什么决定的线程安全问题?
线程安全问题基本是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
2.可以解决多线程并发访问资源的方法有哪些?
主要有三种方式:分别是同步代码块 、同步方法和锁机制(Lock)
其中同步代码块和同步方法是通过关键字synchronized实现线程同步
本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁
二、synchronized关键字各种用法与实例
事实上,synchronized修饰非静态方法、同步代码块的synchronized (this)用法和synchronized (非this对象)的用法锁的是对象,线程想要执行对应同步代码,需要获得对象锁。
synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。
因此,事实上synchronized关键字可以细分为上面描述的五种用法。
1.同步块synchronized (this)
public class Ticket1 extends Thread{private int nums = 0; //出票数private int count =20; //剩余 @Overridepublic void run() {while (true) {synchronized (this) {if(count <= 0) {break;}nums++;count--;try {Thread.sleep(550);} catch (Exception e) {e.printStackTrace();}System.out.println("显示出票信息:"+Thread.currentThread().getName()+"抢到第"+nums+"张票,剩余"+count+"张");}}}public static void main(String[] args) {Ticket1 ticket1 = new Ticket1();Thread anni = new Thread(ticket1,"安妮");Thread jack = new Thread(ticket1,"jack");anni.start();jack.start();}}
这样是同步的,线程获取的是同步块synchronized (this)括号()里面的对象实例的对象锁,这里就是Ticket1 实例对象的对象锁了。
需要注意的是synchronized (){}的{}前后的代码依旧是异步的
2.synchronized (非this对象)的用法锁的是对象
例1:
public class Ticket2 implements Runnable{private int nums = 0; //出票数private int count =25; //剩余//实现线程安全三种方法private final Object lock = new Object();//1.使用私有不变对象锁,使得攻击者无法获取到锁对象(推荐使用)@Overridepublic void run() {while (true) {//2.this 使用对象自身的锁(隐式锁)--对象锁//3.Ticket2.class 给Ticket2加锁 --类锁->使用说明:静态方法则一定会同步,非静态方//法需在单例模式才生效(本例为单例),但是也不能都用静态同步方法,总之用得不好可能会给性能带来极大的影响。synchronized (lock) {if(count <= 0) {break;}nums++;count--;try {Thread.sleep(750);} catch (Exception e) {e.printStackTrace();}System.out.println("显示出票信息:"+Thread.currentThread().getName()+"抢到第"+nums+"张票,剩余"+count+"张");}}}public static void main(String[] args) {Ticket2 ticket2 = new Ticket2();Thread zhangsan = new Thread(ticket2,"张三");Thread zhaoyun = new Thread(ticket2,"赵云");zhangsan.start();zhaoyun.start();}}
例2:
public class Run2 {public static void main(String[] args) {Service service = new Service("xiaobaoge");ThreadA2 a = new ThreadA2(service);a.setName("A");a.start();ThreadB2 b = new ThreadB2(service);b.setName("B");b.start();}}class Service {String anyString = new String();public Service(String anyString){this.anyString = anyString;}public void setUsernamePassword(String username, String password) {try {synchronized (anyString) {System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入同步块");Thread.sleep(3000);System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开同步块");}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class ThreadA2 extends Thread {private Service service;public ThreadA2(Service service) {super();this.service = service;}@Overridepublic void run() {service.setUsernamePassword("a", "aa");}}class ThreadB2 extends Thread {private Service service;public ThreadB2(Service service) {super();this.service = service;}@Overridepublic void run() {service.setUsernamePassword("b", "bb");}}
3.synchronized (class)
public class Run {public static void main(String[] args) {ThreadA a = new ThreadA();a.setName("A");a.start();ThreadB b = new ThreadB();b.setName("B");b.start();}}
class Service {public static void printA() {synchronized (Service.class) {try {System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");Thread.sleep(3000);System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");} catch (InterruptedException e) {e.printStackTrace();}}}public static void printB() {synchronized (Service.class) {System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printB");System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printB");}}
}
4.静态synchronized同步方法
public class Run {public static void main(String[] args) {ThreadA a = new ThreadA();a.setName("A");a.start();ThreadB b = new ThreadB();b.setName("B");b.start();}}class Service {synchronized public static void printA() {try {System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");Thread.sleep(3000);System.out.println("线程名称为:" + Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");} catch (InterruptedException e) {e.printStackTrace();}}synchronized public static void printB() {System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"+ System.currentTimeMillis() + "进入printB");System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"+ System.currentTimeMillis() + "离开printB");}}class ThreadA extends Thread {@Overridepublic void run() {Service.printA();}}class ThreadB extends Thread {@Overridepublic void run() {Service.printB();}
}
5.synchronized修饰非静态方法
public class Run {public static void main(String[] args) {HasSelfPrivateNum numRef = new HasSelfPrivateNum();ThreadA athread = new ThreadA(numRef);athread.start();ThreadB bthread = new ThreadB(numRef);bthread.start();}}
class HasSelfPrivateNum {private int num = 0;synchronized public void addI(String username) {try {if (username.equals("a")) {num = 100;System.out.println("a set over!");Thread.sleep(2000);} else {num = 200;System.out.println("b set over!");}System.out.println(username + " num=" + num);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
class ThreadA extends Thread {private HasSelfPrivateNum numRef;public ThreadA(HasSelfPrivateNum numRef) {super();this.numRef = numRef;}@Overridepublic void run() {super.run();numRef.addI("a");}}
class ThreadB extends Thread {private HasSelfPrivateNum numRef;public ThreadB(HasSelfPrivateNum numRef) {super();this.numRef = numRef;}@Overridepublic void run() {super.run();numRef.addI("b");}}
实验结论:两个线程访问同一个对象中的同步方法是一定是线程安全的。本实现由于是同步访问,所以先打印出a,然后打印出b
这里线程获取的是HasSelfPrivateNum的对象实例的锁——对象锁。
转载于:https://www.cnblogs.com/zhusf/p/10566293.html
java线程同步以及对象锁和类锁解析(多线程synchronized关键字)相关推荐
- java线程同步——条件对象+synchronized 关键字
[0]README 0.1) 本文描述转自 core java volume 1, 源代码为原创,旨在理解 java线程同步--条件对象+synchronized 关键字 的相关知识: 0.2)for ...
- (删)Java线程同步实现二:Lock锁和Condition
在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...
- java同步锁synchronized_Java对象锁和类锁全面解析(多线程synchronized关键字)
本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁.特别的是希望能帮大家理清一些概念. 一.synchronized关键字 synchronized关键字有如下两种 ...
- java线程同步——竞争条件的荔枝+锁对象
[0]README 0.1) 本文描述转自 core java volume 1, 源代码为原创,旨在理解 java线程同步--竞争条件的荔枝+锁对象 的相关知识: 0.2) for full sou ...
- 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )
文章目录 一.线程安全 二.锁机制 ( 类锁 | 对象锁 ) 三.锁分类 ( 轻量级锁 | 重量级锁 ) 一.线程安全 多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量 ...
- Java 对象锁和类锁全面解析
2019独角兽企业重金招聘Python工程师标准>>> 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念. ...
- java中存在对多个对象加锁的情况_Java对象锁和类锁全面解析(多线程synchronized关键字)...
最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...
- Java并发编程-八锁问题带你彻底理解对象锁和类锁
八锁问题带你理解对象锁和类锁 8锁问题演示 1.标准访问 2.在邮件方法中暂停4秒,请问先打印邮件还是短信 3.新增普通sayHello方法,请问先打印邮件还是hello 4.两部手机,请问先打印邮件 ...
- Java对象锁和类锁全面解析(多线程synchronized关键字)
最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...
最新文章
- 网络推广——网络推广专员如何看待网站快照更新快慢问题?
- cocos2d-x初探学习笔记(4)--触屏事件
- SpringMVC4零配置--web.xml
- 1030利用三层交换机实现VLAN间通信
- IDEA中一个工程多个模块(module)分别提交到不同的git服务器
- leetcode算法—两数之和 Two Sum
- 通过ajax传值,出现的乱码和特殊字符问题
- 如何正确的停掉线程?这里面大有门道!
- Spring boot(4) web开发(2) 请求处理、响应处理、模板引擎
- python爬虫和Java爬虫哪个更好
- 如何利用c语言写九九乘法表
- 游戏王抽卡模拟器(概率计算器)
- 简单的社区管理系统(Qt)
- 网站渗透实战试验(仅供参考)
- 电瓶车充电桩收费平台在福建学校的应用
- LayUI可选择可输入下拉框
- Java、JSP地铁线路查询系统
- lucas定理(学习笔记)
- 等一等!看一看!缓一缓!
- 【互动媒体技术赏析作业】
热门文章
- 【CMU】图卷积神经网络中的池化综述,Pooling in Graph Convolutional Neural Network
- 推荐10款Windows系统必备的高效软件!!!
- 人生赢家的三个最基本标准
- 技术非中立,语言非同质:机器翻译正被用于维护文化障碍
- SAP WM Movement Type 里的‘Ref.Stor.Type Search’字段用法初探
- 大脑模拟NLP,高德纳奖得主:神经元集合演算用于句子解析
- 2021-2030 无人机行业十大发展趋势
- 标准出现问题,人工智能正在走向错误的方向
- 现代化机器学习工具,助数据科学家开展更多工程或业务功能
- 如何判断一个对话机器人有多智能?