Java高并发 Synchronized详解(二)

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

//两个线程 t1,t2 同时访问SynchronizedObjectMethod3对象中的Method()方法:
package disappear.request;

public class SynchronizedObjectMethod3 implements Runnable{
    static SynchronizedObjectMethod3 instence = new SynchronizedObjectMethod3();
    @Override
    public void run() {
            Method();
    }
    //争抢的是同一把锁
    public synchronized void Method() {
        System.out.println("My name is :"+Thread.currentThread().getName());
        try{
            Thread.sleep(3000);
        }catch(InterruptedException ie){
            ie.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" is over!");
    }
    public static void main(String [] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
        }
        System.out.println("Over!");
    }
}

1.2、两个线程同时访问两个对象的同步(synchronized)方法

//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法
package Synchronized.Seven.Phenomenon;

public class Phenomenon1 implements Runnable{
    static Phenomenon1 instence1 = new Phenomenon1();
    static Phenomenon1 instence2 = new Phenomenon1();
    public synchronized void Method(){
        System.out.println("My name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" is over!");
    }
    @Override
    public void run() {
        Method();
    }
    public static void main(String [] args){
        Thread  t1 = new Thread(instence1);
        Thread  t2 = new Thread(instence2);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
            
        }
        System.out.println("all is over!");
    }
}

1.3、两个线程访问的是不同对象的同步(synchronized)静态方法

//两个线程 t1,t2 分别访问的是两个Phenomenon1对象中的Method()方法,但是Method()方法是静态方法。
package Synchronized.Seven.Phenomenon;

public class Phenomenon3 implements Runnable{
    static Phenomenon3 instence1 = new Phenomenon3();
    static Phenomenon3 instence2 = new Phenomenon3();
    public static synchronized void Method(){
        System.out.println("My name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" is over!");
    }
    @Override
    public void run() {
        Method();
    }
    public static void main(String [] args){
        Thread  t1 = new Thread(instence1);
        Thread  t2 = new Thread(instence2);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("all is over!");
    }
}

1.4、同时访问同步方法和非同步方法

//两个线程 t1,t2 访问的是一个Phenomenon4对象中的Method1()方法和Method2()方法,但是Method1()方法由synchronized修饰。
package Synchronized.Seven.Phenomenon;

public class Phenomenon4 implements Runnable
{
    static Phenomenon4 instence = new Phenomenon4();
    public synchronized void Method1() {
        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    public void Method2() {
        System.out.println("I'm a commend method,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            Method1();
        }else{
            Method2();
        }
    }
    public static void main(String[] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
            
        }
        System.out.println("all is over!");
    }
}

结论:synchronized 关键字只作用于修饰的一个方法,不会影响同类中的其他方法的并发操作。

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

//两个线程 t1,t2 访问的是一个Phenomenon5对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰。
package Synchronized.Seven.Phenomenon;

public class Phenomenon5 implements Runnable{
    static Phenomenon5 instence = new Phenomenon5();
    public synchronized void Method1() {
        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    public synchronized void Method2() {
        System.out.println("I'm a method by synchronized,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            Method1();
        }else{
            Method2();
        }
    }
    public static void main(String [] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("all is over!");
    }
}

结论:synchronized默认指定了this这个对象,作为他的锁。所以synchronized修饰的两个或者两个以上的方法是相互受到影响的。

1.6、同时访问静态的synchronized方法和非静态的synchronized方法

//两个线程 t1,t2 访问的是一个Phenomenon6对象中的Method1()方法和Method2()方法,两个方法都被synchronized修饰,但是Method1()方法是静态方法,Method2()方法是非静态方法
package Synchronized.Seven.Phenomenon;

public class phenomenon6 implements Runnable{
    static phenomenon6 instence = new phenomenon6();
    //static修饰的背后'锁'是.class对象
    public static synchronized void Method1() {
        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    //没有静态修饰,'锁'是t实例本身his对象.
    public synchronized void Method2() {
        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            Method1();
        }else{
            Method2();
        }
    }
    public static void main(String [] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
        }
        System.out.println("all is over!");
    }
}

结论:静态synchronized修饰的方法和非静态synchronized修饰的方法,之间所获取到的 ’ 锁 ’ 是不相同的。所以两者之间没有影响。

1.7、方法抛出异常后,会释放锁

//
package Synchronized.Seven.Phenomenon;

public class Phenomenon7 implements Runnable{
    static Phenomenon7 instence = new Phenomenon7();
    //static修饰的背后'锁'是.class对象
    public synchronized void Method1() {
        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
            throw new Exception();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    //没有静态修饰,'锁'是t实例本身his对象.
    public synchronized void Method2() {
        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            Method1();
        }else{
            Method2();
        }
    }
    public static void main(String [] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
        }
        System.out.println("all is over!");
    }
}
package Synchronized.Seven.Phenomenon;

public class Phenomenon7 implements Runnable{
    static Phenomenon7 instence = new Phenomenon7();
    //static修饰的背后'锁'是.class对象
    public synchronized void Method1() {
        System.out.println("I'm a synchronized and static method,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        throw new RuntimeException();
        //System.out.println(Thread.currentThread().getName()+"is over!");
    }
    //没有静态修饰,'锁'是t实例本身his对象.
    public synchronized void Method2() {
        System.out.println("I'm a synchronized method ,my name is:"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"is over!");
    }
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            Method1();
        }else{
            Method2();
        }
    }
    public static void main(String [] args){
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){
        }
        System.out.println("all is over!");
    }
}

I’m a synchronized and static method,my name is:Thread-0
Exception in thread “Thread-0” I’m a synchronized method ,my name is:Thread-1
java.lang.RuntimeException at Synchronized.Seven.Phenomenon.Phenomenon7.Method1(Phenomenon7.java:13) at Synchronized.Seven.Phenomenon.Phenomenon7.run(Phenomenon7.java:29)
at java.lang.Thread.run(Thread.java:748)
Thread-1is over!
all is over!

结论:当方法中抛出了异常之后,JVM会帮助我们释放掉,synchronized获得的锁。以至于后序别的线程中的synchronized可以重新获取这把对象锁或类锁。

1.8、总结

1、一个锁只能同时被一个线程获取,没有拿到锁的线程必须等待。
2、每个实例都对应有自己的一把锁,不同实例之间互不影响;例如:当锁对象是 *.class 以及synchronized修饰的static方法的时候,所有的对象共用同一把类锁;
3、无论这个方法是正常执行完毕还是抛出了异常,都会释放掉自身持有的’锁’ ;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值