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 同步锁 作用于 静态方法 和 非静态方法 的 区别的更多相关文章

  1. 在静态方法和非静态方法上加 Synchronized的区别

    Synchronzied 修饰非静态方法==>对象锁 Synchronzied 修饰静态方法==>其实是类锁,因为是静态方法,它把整个类锁起来了: 1.Synchronized修饰非静态方 ...

  2. Java中synchronized用在静态方法和非静态方法上面的区别

    synchronized 修饰在 static方法和非static方法的区别   在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...

  3. 使用synchronized修饰静态方法和非静态方法有什么区别

    前言 最近被问到了这个问题,第一次回答的也是很不好,在此参考网上答案进行整理记录.供大家学习参考. Synchronized修饰非静态方法 Synchronized修饰非静态方法,实际上是对调用该方法 ...

  4. java中静态方法和非静态方法调用的一点小困扰,已解决。

    public static void main(String[] args) { // TODO Auto-generated method stub SimpleGui1B gui=new Simp ...

  5. Java中堆、栈,静态方法和非静态方法的速度问题

           一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储 ...

  6. 转 C#中静态方法与非静态方法区别比较

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  7. C#静态类 静态方法与非静态方法比较

    静态类 在类(class)上加入static修饰,表示该类无法被实例化,并将该类中,无法实例化变量或函数 静态类的主要特性 仅包含静态成员 无法实例化 静态类的本质,时一个抽象的密封类,所以不能被继承 ...

  8. [转]C#静态方法与非静态方法的比较

    http://wenku.baidu.com/view/4e1704084a7302768e9939e0.html C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他 ...

  9. c#静态方法和非静态方法区别

    c#静态方法和非静态方法区别 C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢?让我们来看看最直观的差别:使用了static 修饰符的方法为 ...

随机推荐

  1. 4个优化方法,让你能了解join计算过程更透彻

    摘要:现如今, 跨源计算的场景越来越多, 数据计算不再单纯局限于单方,而可能来自不同的数据合作方进行联合计算. 本文分享自华为云社区<如何高可靠.高性能地优化join计算过程?4个优化让你掌握其 ...

  2. 【dva】如何监听异步请求是否完成(页面loading)

    方案1.你可以在model里面操作 在model里面的state里面声明一个变量state,默认是false,effect函数执行开始就将其改为true,然后等call()然后结束后又将其改为fals ...

  3. 安装火狐浏览器报错找不到VCRUNTIME140_1.DLL

    产生原因参考及下载地址:https://cn.dll-files.com/vcruntime140_1.dll.html vcruntime140_1.dll 相关的错误可能源于多种不同原因.比如,错 ...

  4. [BUUCTF]PWN——jarvisoj_level3

    jarvisoj_level3 附件 步骤 例行检查,32位,nx保护 运行一下程序 32位ida载入,shift+f12没有看到程序里有可以直接利用的后面函数,根据运行时的字符串找到了程序的关键函数 ...

  5. dart系列之:如丝滑般柔顺,操作文件和目录

    目录 简介 File 读取整个文件 以流的形式读取文件 随机访问 文件的写入 处理异常 总结 简介 文件操作是IO中非常常见的一种操作,那么对应dart语言来说,操作文件是不是很简单呢?实际上dart ...

  6. CF116B Little Pigs and Wolves 题解

    Content 有一张 \(n\times m\) 的地图,其中,\(\texttt{P}\) 代表小猪,\(\texttt{W}\) 代表狼.如果狼的上下左右有一头以上的小猪,那么它会吃掉其中相邻的 ...

  7. 使用.NET 6开发TodoList应用(5)——领域实体创建

    需求 上一篇文章中我们完成了数据存储服务的接入,从这一篇开始将正式进入业务逻辑部分的开发. 首先要定义和解决的问题是,根据TodoList项目的需求,我们应该设计怎样的数据实体,如何去进行操作? 长文 ...

  8. WebApi的前端调用

    WebApi前端调用 HTML代码: <!DOCTYPE html><html> <head> <meta charset="utf-8" ...

  9. java 数据类型:集合接口Collection之 Stream 的reduce方法

    Stream 的reduce递归计算 import java.util.ArrayList; import java.util.Arrays; import java.util.List; impor ...

  10. js 让小数四舍五入保留两位小数的函数是?

    js 让小数四舍五入保留两位小数的函数是? 例子:data.relations[i].data[j].toFixed(2) toFixed(2)这个函数就是保留两位小数的作用