一、关于线程安全

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关键字)相关推荐

  1. java线程同步——条件对象+synchronized 关键字

    [0]README 0.1) 本文描述转自 core java volume 1, 源代码为原创,旨在理解 java线程同步--条件对象+synchronized 关键字 的相关知识: 0.2)for ...

  2. (删)Java线程同步实现二:Lock锁和Condition

    在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...

  3. java同步锁synchronized_Java对象锁和类锁全面解析(多线程synchronized关键字)

    本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁.特别的是希望能帮大家理清一些概念. 一.synchronized关键字 synchronized关键字有如下两种 ...

  4. java线程同步——竞争条件的荔枝+锁对象

    [0]README 0.1) 本文描述转自 core java volume 1, 源代码为原创,旨在理解 java线程同步--竞争条件的荔枝+锁对象 的相关知识: 0.2) for full sou ...

  5. 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )

    文章目录 一.线程安全 二.锁机制 ( 类锁 | 对象锁 ) 三.锁分类 ( 轻量级锁 | 重量级锁 ) 一.线程安全 多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量 ...

  6. Java 对象锁和类锁全面解析

    2019独角兽企业重金招聘Python工程师标准>>> 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念. ...

  7. java中存在对多个对象加锁的情况_Java对象锁和类锁全面解析(多线程synchronized关键字)...

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

  8. Java并发编程-八锁问题带你彻底理解对象锁和类锁

    八锁问题带你理解对象锁和类锁 8锁问题演示 1.标准访问 2.在邮件方法中暂停4秒,请问先打印邮件还是短信 3.新增普通sayHello方法,请问先打印邮件还是hello 4.两部手机,请问先打印邮件 ...

  9. Java对象锁和类锁全面解析(多线程synchronized关键字)

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

最新文章

  1. 网络推广——网络推广专员如何看待网站快照更新快慢问题?
  2. cocos2d-x初探学习笔记(4)--触屏事件
  3. SpringMVC4零配置--web.xml
  4. 1030利用三层交换机实现VLAN间通信
  5. IDEA中一个工程多个模块(module)分别提交到不同的git服务器
  6. leetcode算法—两数之和 Two Sum
  7. 通过ajax传值,出现的乱码和特殊字符问题
  8. 如何正确的停掉线程?这里面大有门道!
  9. Spring boot(4) web开发(2) 请求处理、响应处理、模板引擎
  10. python爬虫和Java爬虫哪个更好
  11. 如何利用c语言写九九乘法表
  12. 游戏王抽卡模拟器(概率计算器)
  13. 简单的社区管理系统(Qt)
  14. 网站渗透实战试验(仅供参考)
  15. 电瓶车充电桩收费平台在福建学校的应用
  16. LayUI可选择可输入下拉框
  17. Java、JSP地铁线路查询系统
  18. lucas定理(学习笔记)
  19. 等一等!看一看!缓一缓!
  20. 【互动媒体技术赏析作业】

热门文章

  1. 【CMU】图卷积神经网络中的池化综述,Pooling in Graph Convolutional Neural Network
  2. 推荐10款Windows系统必备的高效软件!!!
  3. 人生赢家的三个最基本标准
  4. 技术非中立,语言非同质:机器翻译正被用于维护文化障碍
  5. SAP WM Movement Type 里的‘Ref.Stor.Type Search’字段用法初探
  6. 大脑模拟NLP,高德纳奖得主:神经元集合演算用于句子解析
  7. 2021-2030 无人机行业十大发展趋势
  8. 标准出现问题,人工智能正在走向错误的方向
  9. 现代化机器学习工具,助数据科学家开展更多工程或业务功能
  10. 如何判断一个对话机器人有多智能?