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. java的父类声明,子类实例化(强制类型转换导致异常ClassCastException)

    一.使用原因 父类声明,子类实例化,既可以使用子类强大的功能,又可以抽取父类的共性. 二.使用要点 1.父类类型的引用可以调用父类中定义的所有属性和方法: 2.父类中方法只有在是父类中定义而在子类中没 ...

  2. 【力扣】973. 最接近原点的 K 个点

    我们有一个由平面上的点组成的列表 points.需要从中找出 K 个距离原点 (0, 0) 最近的点. (这里,平面上两点之间的距离是欧几里德距离.) 你可以按任何顺序返回答案.除了点坐标的顺序之外, ...

  3. 【JS】枚举类型

    https://zhuanlan.zhihu.com/p/79137838 相当于用数字来代替一串字母 /** * 时间:2019年8月18日 * 前端教程: https://www.pipipi.n ...

  4. useEffect无限调用问题

    1.useEfect()的基本用法 const [test,setTest] = useState(1) const init=()=>{ setTest(2) } useEffect(()=& ...

  5. Charles ios设备抓包

    在Mac下做开发,用Fiddler抓包由于离不开Windows比较痛苦,还好有Charles,到官网http://www.charlesproxy.com/可下载到最新版本(若不支持rMBP可拖到Re ...

  6. [BUUCTF]PWN——jarvisoj_level3_x64

    jarvisoj_level3_x64 附件 步骤: 例行检查,64位程序,开启了nx保护 试运行一下程序,看看大概的情况 64位ida载入,习惯性的检索字符串,没有发现可以直接利用的system,估 ...

  7. win10 linux ubuntu子系统 使用adb

    条件 本文已经默认你已经在win10系统下成功配置了ubuntu子系统,所以唯一的条件就是windows上的adb 版本和ubuntu子系统的adb版本一致. 方法 怎么来保证adb 版本一致呢?在本 ...

  8. java 多线程 线程池:多核CPU利用ExecutorService newWorkStealingPool; ForkJoinPool线程池 执行可拆分的任务RecursiveAction;RecursiveTask

    1,给定并行级别: 1,ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队 ...

  9. 分布式NoSQL数据库MongoDB初体验-v5.0.5

    概述 定义 MongoDB官网 https://www.mongodb.com/ 社区版最新版本5.0,其中5.2版本很快也要面世了 MongoDB GitHub源码 https://github.c ...

  10. SpringBoot项目存放微信的验证文件,把微信的验证文件放在根目录下

    我们做微信开发的时候,有时候会有如下要求 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠. 下载文件 将以下文件上传至填写域名或路径指向的w ...