对于synchronized的理解
一、synchronized
同步关键字,分为同步代码块和同步函数
二、对synchronized的理解(未加static关键字)(以下所说:对同步方法和同步代码块均适用)
对象的创建是以类为模板的
1、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,同一时间只能执行一个,另一个必须要等待当前线程执行完才能执行(同一个对象:见下面的testSynchronized,分为两个线程,两个线程访问的是一个方法)(一个对象两个线程一个方法)
例子:
public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test1();
}
},"test3");
thread1.start();
thread3.start();
}
}
结果:

2、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,两个交替进行,因为对象的创建是以类为模板的,所以两个对象都会有自己独立的方法(不同对象:testSynchronized和testSynchronized1,分为两个线程,两个线程访问的是一个方法)(两个对象两个线程一个方法)
例子:和第一个的例子相比仅仅修改了第31行
public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized1.test1();
}
},"test3");
thread1.start();
thread3.start();
}
}
结果:

3、(两个线程同一对象)当一个线程已经访问了该类中的一个synchronized方法,另一个线程就不能再去访问访问其他的synchronized方法(对象锁是锁住了对象,所以只能执行完这个再去执行另一个)(一个对象两个线程两个方法)
例子:
public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public synchronized void test2(){
System.out.println(this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test2();
}
},"test2");
thread1.start();
thread2.start();
}
}
结果:

4、(同一个对象)当一个线程已经访问了一个类的synchronized方法,那么另一个线程也可以访问其他的非synchronized方法,结果是交替进行的(一个对象两个线程两个方法[一个synchronized一个非synchronized的])
进行了同步的方法(加锁方法)和没有进行同步的方法(普通方法)是互不影响的,一个线程进入了同步方法,得到了对象锁,其他线程还是可以访问那些没有同步的方法(普通方法)
例子:
public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//非synchronized
public void test2(){
System.out.println(this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.test2();
}
},"test2");
thread2.start();
thread1.start();
}
}
结果:

三、加了static后现成的执行
1、对于一个类,一个线程访问了加了static的synchronized方法,另一个线程同样可以访问未加static的synchronized方法,所以结果是交替进行,因为类和对象不同(static修饰后锁住的是类,所有对象共享,而没有加static锁住的是对象,只有每个对象私有)(一个对象一个类两个线程两个方法)
例子:
public class TestSynchronized {
public void test1(){
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static synchronized void test2(){
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//对象调用的是该对象自己的方法
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
//类调用的是类方法
TestSynchronized.test2();
}
},"test2");
thread2.start();
thread1.start();
}
}
结果:

2、两个都是被static修饰的synchronized方法,结果是一个线程等待另一个线程执行完才会执行,因为类是一样的(和同一个对象的理解差不多),方法被synchronized修饰只能一个执行完再执行另一个(一个类两个线程两个方法)
例子:
public class TestSynchronized {
public static void test1(){
synchronized(TestSynchronized.class) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static synchronized void test2(){
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
TestSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
TestSynchronized.test2();
}
},"test2");
thread2.start();
thread1.start();
}
}
结果:

补充:
面试的一道题:
一个只被synchronized修饰的方法fun(),现有两个对象a,b,分别是两个线程t1,t2
①a.fun()和b.fun()可以同时进行吗?
答:可以,因为是两个为不同的对象,对象的创建是以类为模板的,所以这两个对象中都会有自己的fun()方法,所以两个线程开启后会交替进行,如上面的二2
②回答完可以后,怎么可以让两个分开进行即一个完了之后再进行另一个?
答:给方法加上static关键字,static锁住了类,此时锁为“类锁”,所以虽然对象不一样但是类都是一样的,所以简单说就是一个类两个线程调用一个方法,肯定是一个执行完再执行另一个
对于synchronized的理解的更多相关文章
- Java中synchronized关键字理解
好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...
- synchronized的理解
用法解释 synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调 ...
- @synchronized深入理解
@synchronized是线程同步锁,易用.可读性高. @synchronized(self) { 临界区 } 利用如下命令将其重写 clang -rewrite-objc file 得到C++实 ...
- Java线程同步synchronized的理解
JVM中(留神:马上讲到的这两个存储区只在JVM内部与物理存储区无关)存在一个主内存(Main Memory),Java中所有的变量存储在主内存中,所有实例和实例的字段都在此区域,对于所有的线程是共享 ...
- synchronized(this) 与 synchronized(class) 理解
1.概念 synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的. 锁机制有如下两种特性: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机 ...
- java并发编程--Synchronized的理解
synchronized实现锁的基础:Java中每一个对象都可以作为锁,具体表现为3种形式. (1)普通同步方法,锁是当前实例对象 (2)静态同步方法,锁是当前类的Class对象 (3)同步方法块,锁 ...
- 【多线程与高并发原理篇:4_深入理解synchronized】
1. 前言 越是简单的东西,在深入了解后发现越复杂.想起了曾在初中阶段,语文老师给我们解说<论语>的道理,顺便给我们提了一句,说老子的无为思想比较消极,学生时代不要太关注.现在有了一定的生 ...
- volatile synchronized AtomicInteger的区别
在网络上看了很多关于他们两个的区别与联系,今天用自己的话表述一下: synchronized 容易理解,给一个方法或者代码的一个区块加锁,那么需要注意的是,加锁的标志位默认是this对象,当然聪明的你 ...
- Synchronized用法原理和锁优化升级过程(面试)
简介 多线程一直是面试中的重点和难点,无论你现在处于啥级别段位,对synchronized关键字的学习避免不了,这是我的心得体会.下面咱们以面试的思维来对synchronized做一个系统的描述,如果 ...
随机推荐
- javaweb基础整理随笔------jstl与el表达式
虽然jsp中可以写java代码,但是现在不推荐这么做. jsp虽然本质是servlet,但是主要作用只是视图,视图的任务就是显示响应,而不是在JSP中做任何关于程序控制和业务逻辑的事情.所以在JSP页 ...
- SpringBoot:Web开发
西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 , 基于atguigu 1.5.x 视频优化 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处 ...
- Scala集合(四)
1. 集合 集合主要有三种: Sequence Map Set sequence是一种线性元素的集合,可能会是索引或者线性的(链表).map是包含键值对的集合,就像Java的Map,set是包含无重复 ...
- DT-06 For AT
乐鑫官方AT指令固件- 最新1.5.4版本 此固件仅支持AT指令对模块进行操作. 1.DT-06固件的烧录 1.1打开ESP模块下载工具ESPFlashDownloadTool,选择需要下载的固件,填 ...
- (二十八)c#Winform自定义控件-文本框(一)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- 【JS档案揭秘】第二集 Event loop与执行栈
我时常在思考关于JS的很多知识在工作中有什么用?是否只能存在于面试这种理论性的东西中,对于我们的业务和工作,它们又能扮演怎样的角色.以后在JS档案揭秘的每一期里,都会加入我对于业务的思考,让这些知识不 ...
- MongoDB实现评论榜
Mongodb很适合做这件事,api的调用仅仅是使用到了入门级别的CRUD,理清楚了思路,编码也会顺风顺水,所以你会发现我在这篇博客中说的比编码还多 评论榜预期的功能 就像是StackOverFlow ...
- IntelliJ IDEA 2019 快捷键终极大全,速度收藏!
转载注明:https://blog.csdn.net/WantFlyDaCheng/article/details/100078777 自动代码 查询快捷键 其他快捷键 调试快捷键 重构 十大Inte ...
- 90002CAD相关操作
第一章 初识CAD 1.1 CAD能干什么 (1)绘制机械图/建筑图/装修图等二维复杂工程图的不二之选.二维设计软件的王者. (2)CAD可以绘制平面图.轴测图(二维线框表示三维图形).立体图(三 ...
- MSIL实用指南-生成break和continue
break和continue本质都是标签的跳转