深入研究 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 修饰符的方法为 ...
随机推荐
- 小飞机可以解决git clone没有返回的问题吗?
[1]Linux如何使用小飞机? 以ss为例,先下载客户端: https://www.mediafire.com/folder/xag0zy318a5tt/Linux 下载客户端以后,右键把权限中&q ...
- ICCV2021 | 用于视觉跟踪的学习时空型transformer
前言 本文介绍了一个端到端的用于视觉跟踪的transformer模型,它能够捕获视频序列中空间和时间信息的全局特征依赖关系.在五个具有挑战性的短期和长期基准上实现了SOTA性能,具有实时性,比 ...
- python爬虫期末复习
python期末复习 选择题 以下选项中合法的是(A). A 爬取百度的搜索结果 B 爬取淘宝的商品数据 C 出售同学的个人信息 D 为高利贷提供技术服务 网站的根目录下有一个文件告诉爬虫哪些内容可以 ...
- Gitlab-CICD实践篇
一.背景 随着公司项目使用gitlab越来越多,业务发布的次数越来越频繁,对于发布效率提出了更高的要求.从2012开始,Gitlab官方开始集成了Continuous Integration (CI) ...
- 图数据库HugeGraph:HugeGraph-Hubble基于Web的可视化图管理初体验
原创/朱季谦 一.HugeGraph-Hubble简介 关于HugeGraph,官方资料是这样介绍的,它是一款易用.高效.通用的开源图数据库系统(Graph Database), 实现了 Apache ...
- 当动态桌面遇上 HTML5
DreamScene2 + HTML5 = 无限可能.时隔一周,DreamScene2 动态桌面经过几个小版本的迭代,修复了一些问题并且功能也得到了增强.欢迎 Star 和 Fork https:// ...
- Linux中find命令与三剑客之grep和正则
昨日内容回顾 1.每个月的3号.5号和15号,且这天时周六时 执行 00 00 3,5,15 * 6 2.每天的3点到15点,每隔3分钟执行一次 */3 3-15 * * * 3.每周六早上2点半执行 ...
- vim 默认配置
vim ~/.vimrc 然后输入常用的需要用的命令,然后保存,这个每次启动VIM都会自动配置.当然你也可以在VIM里面按":"之后输入如下命令,但是下次启动之后设置就会丢失了. ...
- 账号不允许远程访问服务器上的mysql数据库的解决办法host is not allowed to connect to this mysql
改表法.可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 "use ...
- centos使用shell脚本定时备份docker中的mysql数据库
shell脚本 #!/bin/bash #容器ID container_id="6b1faea2b4d7" #登录用户名 mysql_user="root" # ...