java线程学习之synchronized关键字
关键字synchronized的作用是实现线程间的同步。它的任务是对同步的代码加锁。一个代码块同时只能有同一个线程进行读和写操作,从而保证线程间是安全的。
线程安全的概念是:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。反之就是线程不安全的。
一、为什么要用synchronized?
举个例子,老王有张储蓄卡,里面有一万块钱,老王通过无卡取现要取八千,操作过程中,会先查询储蓄金额,发现是一万,当输入八千的时候系统会让他支取。如果在老王的媳妇在这时拿着卡通过柜台要支取七千块钱,如果取钱的代码没有synchronized同步控制,他们同时进行查询的操作,发现金额是一万,两人输入金额同时进行取钱操作,就有可能都能取出需要的钱来,共计15000,这样的话,银行就会亏了,显示也是不安全的。
如果上个例子理解不了,那么看下面例子:
public class TestSynchorized implements Runnable {
Timer timer = new Timer();
public static void main(String[] args) {
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
public void run(){
timer.add(Thread.currentThread().getName());
}
}
class Timer{
private static int num = 0;
public void add(String name){
num ++;
try {Thread.sleep(1);}
catch (InterruptedException e) {}
System.out.println(name+", 你是第"+num+"个使用timer的线程");
}
}
运行结果为:

在上面19行如果加了synchronized 关键字后的结果

为什么这样呢:
先分析没加的时候,主线程创建了线程 t1 和线程 t2 , t2 先执行Timer类,这时执行完 num++,num的值为1此时线程 执行 Thread.sleep(1) 语句, t2 线程休眠1毫秒,此时 t1 线程执行Timer类,同样执行完 num++语句,num的值为2,此时线程 执行 Thread.sleep(1) 语句,t1 线程进行休眠 。 t2休眠结束,继续执行打印输出语句,随后 t1 也休眠结束,继续执行打印输出语句。
加完synchronized后执行情况呢,同样 t1 先执行执行到 add(String name) 方法,发现有 synchronized ,此时就会独占此资源,即使是在休眠的时候也不允许 t2 执行 add(String name) 方法,只有当 t1 把add 方法执行完毕退出去后,才让 t2 执行 add(String name) 方法。
可能会有疑问,为什么没加 synchronized 关键字前 是 t2 先执行,加了 synchronized 后是 t1 先执行? 其实java虚拟机jvm执行线程的时候的顺序跟书写代码的顺序无关,跟cpu执行线程的顺序有关,执行的时候,谁在前,谁就先执行。这个当然不是绝对的 ,它还受到优先级的影响。但优先级一样的时候,是这样的。
二、synchronized用法
1、给指定的对象加锁,进入同步代码前要获得当前实例的锁。
2、直接作用于实例方法,相当于对当前实例加锁,同步代码前要获得实例的锁。
3、直接作用于静态方法,相当于对当前类加锁,同步代码前要获得当前类的锁。
三、synchronized方法与synchronized代码块
synchronized静态方法的锁的示例:

synchronized代码块的示例:

四、synchronized的作用
1、synchronized可确保线程同步,线程安全。正如之上所言。
2、synchronized能保证线程间的可见性。
可见性:一个线程对共享变量值的修改,能够及时的被其他线程看到。
synchronized可以完全替代volative的功能,只是在使用上没有volative使用方便。
3、synchronized保证线程间的有序性。
因为synchronized限制每次只能允许一个线程可以访问代码块,因此无论怎么使用同步块内的代码如何被打乱顺序,只要保证串行语义一致,那么执行结果总是一样的。而其他访问线程,又必须在获得锁后方能进入代码块读取数据,因此,看到的最终结果并不取决于代码的执行过程,从而有序性自然得到了解决。
java线程学习之synchronized关键字的更多相关文章
- java线程学习之volatile关键字
volatile变量的主要作用:是使变量在多个线程间可见. 在java中每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存的变量值的拷贝.当线程执行时,它在自己的工作内存区操作这些变量,为 ...
- java高并发系列 - 第10天:线程安全和synchronized关键字
这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...
- JAVA多线程之Synchronized关键字--对象锁的特点
一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...
- Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...
- 从线程池到synchronized关键字详解
线程池 BlockingQueue synchronized volatile 前段时间看了一篇关于"一名3年工作经验的程序员应该具备的技能"文章,倍受打击.很多熟悉而又陌生的知识 ...
- Java线程同步(synchronized)——卖票问题
卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1, ...
- Java多线程4:synchronized关键字
原文:http://www.cnblogs.com/skywang12345/p/3479202.html 1. synchronized原理在java中,每一个对象有且仅有一个同步锁.这也意味着,同 ...
- 学习java线程学习笔记
线程:代码执行的一个分支 主要作用是提高了效率,cpu能同时执行多个部分的代码. 线程的创建:两种方式 a.继承于thread类,重写run方法. b. ...
- [多线程] 线程中的synchronized关键字锁
为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...
随机推荐
- Jmeter遇到打不开的问题
1.JDK的版本,一定版本的jmeter需要特定版本以上的JDK支持,比如此次运行的apache-jmeter-2.12,就需要JDK1.6以上的版本支持.我原来装的是JDK1.5,配置好JMETER ...
- python mysql 单表查询 多表查询
一.外键 变种: 三种关系: 多对一 站在左表的角度: (1)一个员工 能不能在 多个部门? 不成立 (2)多个员工 能不能在 一个部门? 成立 只要有一个条件成立:多 对 一或者是1对多 如果两个条 ...
- 深度好文 | 在阿里做了5年技术Leader,我总结出了这些套路!
导读:阿里巴巴高级技术专家云狄将为大家从管理的角度分享技术TL的核心职责,这其中包括团队建设.团队管理.团队文化.沟通与辅导.招聘与解雇等,希望与大家共同探讨.交流. 背景 互联网公司的技术团队管理通 ...
- netbeans10支持php7.1-7.3
2019年1月16日10:56:49 官方发布时间2018年12月27日 PHP支持 NetBeans 10的所有PHP支持都是由我们的NetBeans提交者 Junichi Yamamoto提供的. ...
- 一码阻塞,万码等待:ASP.NET Core 同步方法调用异步方法“死锁”的真相
在我们 2015 年开始的从 .NET Framework 向 .NET Core 迁移的工程中,遇到的最大的坑就是标题中所说的--同步方法中调用异步方法发生"死锁".虽然在 .N ...
- Head First Python-python面向对象
与大多数其他的编程语言一样,Python容许创建并定义面向对象的类,类可以将代码与代码处理的数据相关联. 对于更加复杂的数据,一般的列表已经不能满足需求了. 我们可以使用字典dict将数据值与键相关联 ...
- 二、springboot使用jpa
花了几天时间,好好看了看springboot的jpa部分,总结了常用的形式. 1.通过STS工具添加jpa的依赖项 要连mysql,测试的时候需要web,顺便添加了lombok不写set和get方法了 ...
- SoupUI 5.1.2(专业版)下载(含破解文件)
包内含原安装包和破解文件,仅用于技术交流,切勿用于商业用途. 安装教程参考:https://www.cnblogs.com/miaojjblog/p/9778839.html 安装包及破解文件下载地址 ...
- mysql8.0.13免安装版的安装配置详解
一.下载 下载地址:https://dev.mysql.com/downloads/mysql/ 二.解压到某个目录,例如:D:/mysql/mysql-8.0.13-winx64 三.配置环境变量 ...
- com.alibaba.druid.pool.DruidDataSource : {dataSource-2} init error
这几天准备写一个项目,其中的整合druid的时候,发现出现了下面这个错误.找了好久都没有找到.网上的各种解决方法都不对. 2018-11-07 16:26:28.940 INFO 19684 --- ...