深入研究 synchronized 同步锁 作用于 静态方法 和 非静态方法 的 区别
1.前言
众所周知, synchronized 是同步锁 ,虽然在底层又细分了无锁、偏向锁、轻量级锁、自旋锁 以及重量级锁 机制,
这些底层锁知道一下原理即可 ,【想要 了解 这篇 博文 有 解释 : https://blog.csdn.net/u013256816/article/details/51204385 】
我这篇随笔专门研究与总结 关于 synchronized 加 在 同一个类里的 静态 和非静态 方法前 有什么不一样的影响 。
这都是因为我看到的一道题引起的:

答案是 BE
我想问为什么?
查找博客资料 ,都是很笼统地解释
static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对
象),那么static获取到的锁,是属于类的锁。而非static方法获取到的锁,是属于当前对象
的锁。所以,他们之间不会产生互斥。
看的我一脸懵逼。。。。。。
当然可以清楚地知道
加了synchronized 且有static 的方法称为类锁,
没有static 的方法称为对象锁。
经过测试总结:
(1)多线程使用同一个对象,只允许同时使用一个对象锁,一个类锁,
其他操作搭配都互斥,只能等前一个线程解锁才能让下一个线程使用;
(2)多线程分别 new 一个对象,允许同时使用任意的对象锁,也允许对象锁和
一个类锁同时使用,但是类锁不能够同时使用,会互斥,只能等前一个线程解锁才能让下一个线程使用;
2.操作
(1)目录结构

(2)准备一个含有对象锁和类锁的 类

package com.example.javabaisc.lock;
public class MSynchronized {
public synchronized void method1(String name) throws InterruptedException {
int i = 0;
while (true) {
i++;
System.out.println(name + "我是方法1,当前数字是" + i);
if (i > 4) {
System.out.println(name + "我是方法1,退出");
break;
}
Thread.sleep(1000);
}
}
public synchronized void method2(String name) throws InterruptedException {
int i = 0;
while (true) {
i++;
System.out.println(name + "我是方法2,当前数字是" + i);
if (i > 4) {
System.out.println(name + "我是方法2,退出");
break;
}
Thread.sleep(1000);
}
}
public static synchronized void method3(String name) throws InterruptedException {
int i = 0;
while (true) {
i++;
System.out.println(name + "我是方法3,当前数字是" + i);
if (i > 4) {
System.out.println(name + "我是方法3,退出");
break;
}
Thread.sleep(1000);
}
}
public static synchronized void method4(String name) throws InterruptedException {
int i = 0;
while (true) {
i++;
System.out.println(name + "我是方法4,当前数字是" + i);
if (i > 4) {
System.out.println(name + "我是方法4,退出");
break;
}
Thread.sleep(1000);
}
}
}
(3)测试类
package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
}
}
内容在测试里详细补充【注意,不可使用@Test注解启动 用户线程,否则所有线程都会随用户线程结束而结束】
3.测试
1)测试 :多线程使用同一个对象
(1)同时使用同一个对象锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
//共用对象
MSynchronized mSynchronized = new MSynchronized();
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
mSynchronized.method1("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
(2)同时使用不同的的对象锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
//共用对象
MSynchronized mSynchronized = new MSynchronized();
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
mSynchronized.method2("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
(3)一个线程使用对象锁,一个使用类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
//共用对象
MSynchronized mSynchronized = new MSynchronized();
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
mSynchronized.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:可以同时使用
(4)同时使用同一个类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
//共用对象
MSynchronized mSynchronized = new MSynchronized();
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
mSynchronized.method4("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
mSynchronized.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
(5)同时使用不同的的类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
//共用对象
MSynchronized mSynchronized = new MSynchronized();
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
mSynchronized.method3("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
mSynchronized.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
===================================================================================
分割线
===================================================================================
2)测试 :多线程分别 new 一个对象
(1)同时使用同一个对象锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
MSynchronized mSynchronized = new MSynchronized();
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
MSynchronized mSynchronized2 = new MSynchronized();
mSynchronized2.method1("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:可以同时使用
(2)同时使用不同的的对象锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
MSynchronized mSynchronized = new MSynchronized();
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
MSynchronized mSynchronized2 = new MSynchronized();
mSynchronized2.method2("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:可以同时使用
(3)一个线程使用对象锁,一个使用类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
MSynchronized mSynchronized = new MSynchronized();
mSynchronized.method1("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
MSynchronized mSynchronized2 = new MSynchronized();
mSynchronized2.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:可以同时使用
(4)同时使用同一个类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
MSynchronized mSynchronized = new MSynchronized();
mSynchronized.method4("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
MSynchronized mSynchronized2 = new MSynchronized();
mSynchronized2.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
(5)同时使用不同的的类锁

package com.example.javabaisc.lock;
public class SynT {
public static void main(String[] args){
Thread s1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("=========我是线程1==========");
MSynchronized mSynchronized = new MSynchronized();
mSynchronized.method3("我是线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread s2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// System.out.println("==========我是线程2========");
MSynchronized mSynchronized2 = new MSynchronized();
mSynchronized2.method4("我是线程2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动
s1.start();
s2.start();
}
}
打印结果

结论:互斥,不能同时使用
4.总结
(1)在多线程使用同一个对象的测试中,只允许同时使用一个对象锁,一个类锁,
其他操作搭配都互斥,只能等前一个线程解锁才能让下一个线程使用;
(2)在多线程分别 new 一个对象的测试中,允许同时使用任意的对象锁,也允许对象锁和
一个类锁同时使用,但是类锁不能够同时使用,会互斥,只能等前一个线程解锁才能让下一个线程使用;
深入研究 synchronized 同步锁 作用于 静态方法 和 非静态方法 的 区别的更多相关文章
- 在静态方法和非静态方法上加 Synchronized的区别
Synchronzied 修饰非静态方法==>对象锁 Synchronzied 修饰静态方法==>其实是类锁,因为是静态方法,它把整个类锁起来了: 1.Synchronized修饰非静态方 ...
- Java中synchronized用在静态方法和非静态方法上面的区别
synchronized 修饰在 static方法和非static方法的区别 在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...
- 使用synchronized修饰静态方法和非静态方法有什么区别
前言 最近被问到了这个问题,第一次回答的也是很不好,在此参考网上答案进行整理记录.供大家学习参考. Synchronized修饰非静态方法 Synchronized修饰非静态方法,实际上是对调用该方法 ...
- java中静态方法和非静态方法调用的一点小困扰,已解决。
public static void main(String[] args) { // TODO Auto-generated method stub SimpleGui1B gui=new Simp ...
- Java中堆、栈,静态方法和非静态方法的速度问题
一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储 ...
- 转 C#中静态方法与非静态方法区别比较
C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...
- C#静态类 静态方法与非静态方法比较
静态类 在类(class)上加入static修饰,表示该类无法被实例化,并将该类中,无法实例化变量或函数 静态类的主要特性 仅包含静态成员 无法实例化 静态类的本质,时一个抽象的密封类,所以不能被继承 ...
- [转]C#静态方法与非静态方法的比较
http://wenku.baidu.com/view/4e1704084a7302768e9939e0.html C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他 ...
- c#静态方法和非静态方法区别
c#静态方法和非静态方法区别 C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢?让我们来看看最直观的差别:使用了static 修饰符的方法为 ...
随机推荐
- PHP之CURL实现含有验证码的模拟登录
博主最近在为学校社团写一个模拟登录教务系统来进行成绩查询的功能,语言当然是使用PHP啦,原理是通过php数据传输神器---curl扩展,向学校教务系统发送请求,通过模拟登录,获取指定url下的内容. ...
- testng 执行多个suite
我们知道testng的配置文件,一个.xml里面只能有一个suite,那么如果想要设置多个suite怎么弄呢?这个时候我们需要用到testng的标签<suite-files>. 下面说一下 ...
- pipeline post指令
目录 一.介绍 二.参数说明 三.使用实例 一.介绍 post步骤包含的是在整个pipeline或阶段完成后一些附加的步骤.post步骤是可选的,所以并不包含在声明式pipeline最简结构中,但这并 ...
- Python绘制折线图
一.Python绘制折线图 1.1.Python绘制折线图对应代码如下图所示 import matplotlib.pyplot as pltimport numpy as np from pylab ...
- 一文详解 纹理采样与Mipmap纹理——构建山地渲染效果
在开发一些相对较大的场景时,例如:一片铺满相同草地纹理的丘陵地形,如果不采用一些技术手段,就会出现远处的丘陵较近处的丘陵相比更加的清晰的视觉效果,而这种效果与真实世界中近处的物体清晰远处物体模糊的效果 ...
- [BUUCTF]REVERSE——firmware
firmware 附件 步骤: 检查文件没有看出什么,ida载入一堆乱码,看了其他师傅的wp才知道要先binwalk对文件进行提取 120200.squashfs这是一个linux的压缩文件 我们需要 ...
- Table.Distinct取唯/众数….Distinct/Mode/判断…IsDistinct(Power Query 之 M 语言)
数据源: "姓名""基数""个人比例""个人缴纳""公司比例""公司缴纳"&qu ...
- Ribbon——负载均衡
一.什么是Ribbon Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起.Ribbon客户端组件提供一系列完善的配置项如连接超 ...
- Do PDB Files Affect Performance?
After a detour into Historical Debugging, it's time to come back to return to answering questions ab ...
- 【LeetCode】412. Fizz Buzz 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目大意 解题方法 方法一:遍历判断 方法二:字符串相加 方法三:字典 日期 [L ...