多线程访问同步方法的7种情况

news/2024/5/17 16:39:43 标签: synchronized

1、两个线程同时访问一个对象的同步方法

public class SynchroizedObject extends Thread{

    static SynchroizedObject instance = new SynchroizedObject();
    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        method();
    }

    public synchronized void method () {
        System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}

运行结果:

我的对象锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束

同一个实例使用同一把锁,两个线程使用同一把锁,必然有一个处于等待,一个线程执行完成,另一个线程才可以执行。

2、两个线程访问的是两个对象的同步方法

public class SynchroizedObject2 extends Thread{

    static SynchroizedObject2 instance1 = new SynchroizedObject2();
    static SynchroizedObject2 instance2 = new SynchroizedObject2();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        synchronized (this) {
            System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }
    }


}

运行结果:

我的对象锁的方法修饰符形式,我叫Thread-2
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-2运行结束
Thread-3运行结束

结果线程同时开始,同时结束,之间不会受干扰,因为对象不是同一个,所以不会受干扰。

3、两个线程访问的是synchronize 的静态方法

public class SynchroizedObject3 extends Thread{

    static SynchroizedObject3 instance1 = new SynchroizedObject3();
    static SynchroizedObject3 instance2 = new SynchroizedObject3();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        method();
    }

    public static synchronized void method () {
        System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }


}

运行结果

我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-3运行结束

只要方法是静态的,锁对应的就是一把,所以线程是一个执行完成,再去执行下一个线程。

4、同时访问同步方法与非同步方法

public class SynchroizedObject4 implements Runnable {

    static SynchroizedObject4 instance = new SynchroizedObject4();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized  void method1() {
        System.out.println("我的加锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public  void method2() {
        System.out.println("我的没加锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我的加锁的方法修饰符形式,我叫Thread-0
我的没加锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
Thread-0运行结束

线程0和线程1几乎同时开始同时结束,synchronized  关键字只作用于指定的method1方法中,没有加上synchronized  这个关键字方法,不受影响,不会由于其他方法加上synchronized  而受到影响。非同步方法不受到影响。

5、访问一个对象的不同的普通同步方法

public class SynchroizedObject5 implements Runnable {

    static SynchroizedObject5 instance = new SynchroizedObject5();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized  void method1() {
        System.out.println("我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized void method2() {
        System.out.println("我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我叫Thread-0
Thread-0运行结束
我叫Thread-1
Thread-1运行结束

同一个实例中,这两个方法没有办法同时运行,会出现串行的情况。

6、同时访问静态synchronize和非静态synchronize方法

public class SynchroizedObject6 implements Runnable {

    static SynchroizedObject6 instance = new SynchroizedObject6();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized static void method1() {
        System.out.println("我是静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized void method2() {
        System.out.println("非静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我是静态加锁方法,我叫Thread-0
非静态加锁方法,我叫Thread-1
Thread-0运行结束
Thread-1运行结束

运行结果几乎同时运行,同时结束,所指定的锁对象不是同一个锁,所以可以同时运行。

7、方法抛异常,会释放锁

方法抛异常后,会释放锁。展示不抛出异常前和抛出异常后的对比:一旦抛出了异常,第二个线程会立刻进入同步方法,意味着锁已经释放。

public class SynchroizedObject7 implements Runnable {

    static SynchroizedObject7 instance = new SynchroizedObject7();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized void method1() {
        System.out.println(" 我是静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
        throw new RuntimeException();
//        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized void method2() {
        System.out.println(" 非静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我是静态加锁方法,我叫Thread-0
 非静态加锁方法,我叫Thread-1
Exception in thread "Thread-0" java.lang.RuntimeException
	at com.test5.SynchroizedObject7.method1(SynchroizedObject7.java:39)
	at com.test5.SynchroizedObject7.run(SynchroizedObject7.java:25)
	at java.lang.Thread.run(Thread.java:748)
Thread-1运行结束

抛出异常之后,不需要手动手动释放锁,由jvm进行释放锁。

 

 


http://www.niftyadmin.cn/n/1087123.html

相关文章

扩展WCF操作行为

使用IParameterInspector, IOperationBehavior,Attribute(参数检查器、操作行为接口和标签)扩展WCF操作行为 开发环境: VS2008 SP1 WIN2008 SP2WCF允许我们在端点Endpoint、消息message、操作Operation、参数Parameter中扩展WCF。本文简单介绍如何截获操作的参数来扩…

StringBuffer 传值的小问题

下面是一个小例子: public static void main(String []args) {StringBuffer str1 new StringBuffer("good");StringBuffer str2 new StringBuffer("bad");test (str1, str2);System.out.println(str1.toString());System.out.println(str2…

BZOJ 3354 Hiring

BZOJ 3354 考虑枚举Level1给多少钱 那就是有些人不会来 来的人贪心得从Level最小的开始选 这个贪心正确性显然 哪怎么枚举呢 每个人可以算出给1Level多少钱他才来 对这个值排序,从小到大扫,维护选的人的集合 怎么维护? 对于一个新人能要就要(…

子进程自父进程继承什么或未继承什么

知道子进程自父进程继承什么或未继承什么将有助于我们。下面这个名单会因为 不同Unix的实现而发生变化,所以或许准确性有了水份。请注意子进程得到的是 这些东西的 *拷贝*,不是它们本身。 由子进程自父进程继承到: 进程的资格(真实(real)/有…

对象转换 json 字符串和 json转换对象的几种方式

参考网上的文章,做了一个关于json的总结,进行留存帮助以后阅读,希望可以帮助到大家。 1、使用阿里巴巴的fastjson方式处理。 测试实体类 public class User {// 用户编号private String userNo;// 用户名字private String name;public Str…

【Python基础】05_Python中的while循环

1.程序的三大流程介绍 顺序 —— 从上到下,顺序执行分支 —— 根据条件判断,决定代码的分支循环 —— 让特定代码执行2.while 基本语法 while 条件(判断 计数器 是否达到 目标次数): 条件满足时,做的事情1 条件满足时,做的事情2 ……

设计模式装饰器模式

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 装饰器模式角色 Component 定义一个对象接口,可以给这些对象动态地添加职责。 ConcreteComponent 是定义了一个…

python 第十四章 装饰器

# 开放封闭原则: # 扩展是开放的(增加新功能) # 修改源码是封闭(修改已经实现的功能)# 在不改变源代码及调用方式的基础下额外增加新的功能# 装饰器:用来装饰的工具# 版一:import time # start_time time.time() # def func(): # time.sleep(2) #睡眠 (模拟网络延时) # …