高并发处理之Synchronized学习(五)

访问同步方法的7种情况
1.两个线程同时访问一个对象的同步方法
两个不同的实例,访问同一个对象的同步方法,所运用的锁默认使用的是this,以this对象作为他的锁,所以说,他们使用的是同一把锁,在争抢同一把锁的时候,他们必然要相互等待,因为只能有一个方法持有锁
代码如下:

package com.gwh.lock.test;

/**
 * 对象锁 实例2 方法锁形式
 * 1.两个线程同时访问一个对象的同步方法
 */
public class SynchronizedObjectMethod3 implements  Runnable{
    public static SynchronizedObjectMethod3 objectMethod3=new SynchronizedObjectMethod3();
    @Override
    public void run() {
        method();
    }
    public synchronized void  method(){
        System.out.println("我是对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(objectMethod3);
            Thread t2=new Thread(objectMethod3);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}

结果如下
在这里插入图片描述
2.两个线程访问的是两个对象的同步方法
两个线程访问的是两个对象的同步方法,他们之间是不会受到干扰的,原因是,他们真正所使用的锁对象不是同一个,所以不敢扰
代码如下:

package com.gwh.lock.test;

/**
 * 对象锁实例1 代码块形式
 * 2.两个线程访问的是两个对象的同步方法
 */
public class SychronizedObjectCodeBlock2 implements  Runnable{
    public static SychronizedObjectCodeBlock2 objectCodeBlock2=new SychronizedObjectCodeBlock2();
    //不是用this是因为,可能在同一段代码中,会有多个synchronized代码块,他们不会ishi同时一个执行其他的不执行,所以我们新建一个锁对象
    Object lock1=new Object();
    Object lock2=new Object();

    @Override
    public void run() {
        //使用锁的对象不同会对执行的结果带来不同的影响
        synchronized (lock1){
            try {
                System.out.println("我是对象锁1的代码块形式,我叫"+Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"对象锁1执行结束");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
      /* synchronized (lock2){
           try {
               System.out.println("我是对象锁2的代码块形式,我叫"+Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"对象锁2执行结束");
           }catch (Exception e){
               e.printStackTrace();
            }
       }
*/
    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(objectCodeBlock2);
            Thread t2=new Thread(objectCodeBlock2);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }

            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

结果如下:
在这里插入图片描述
3.两个线程访问的是Synchronized的静态方法
他们会一个一个的执行,锁生效
代码如下:

package com.gwh.lock.test;

/**
 * 类锁的第一种形式,static形式
 * 3.两个线程访问的是Synchronized的静态方法
 */
public class SynchronizedClassStatic4 implements  Runnable{

    public static SynchronizedClassStatic4 classStatic4=new SynchronizedClassStatic4();
    public static SynchronizedClassStatic4 classStatic5=new SynchronizedClassStatic4();

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

    public  static synchronized void method(){ System.out.println("我是类锁的第一种形式:static形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");


    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(classStatic4);
            Thread t2=new Thread(classStatic5);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

结果如下:
在这里插入图片描述
4.同时访问同步和非同步方法
非同步方法不会受到影响
因为synchronized这个关键字,只会作用于你修饰的一个方法中,他不会影响到没加修饰符的方法
代码如下:

package com.gwh.lock.test;

/**
 * 4.同时访问同步和非同步方法
 */
public class SynchronizedYesAndNo6 implements  Runnable{
  public static SynchronizedYesAndNo6 yesAndNo6=new SynchronizedYesAndNo6();

    @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 (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public void method2(){
        System.out.println("我是没加锁的方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(yesAndNo6);
            Thread t2=new Thread(yesAndNo6);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

结果如下
在这里插入图片描述
5.访问一个对象的不同的普通同步方法(非static)
synchronized虽然没有明确指定使用哪个锁对象,但是他本质上是指定了this作为他的锁,所以对于同一个实例来讲,这两个方法所使用的this是一样的,所以这两个方法没法同时运行
代码如下:

package com.gwh.lock.test;

/**
 * 访问一个类的不同的普通同步方法
 */
public class synchronizedDifferentMethod7 implements  Runnable{
    public static synchronizedDifferentMethod7 differentMethod7=new synchronizedDifferentMethod7();
    @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 (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public synchronized void method2(){
        System.out.println("我是加锁的方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(differentMethod7);
            Thread t2=new Thread(differentMethod7);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}

结果如下:
在这里插入图片描述
6.同时访问静态Synchronized和非静态Synchronized方法
两个方法会同时运行,原因是:他们所指定的锁对象,不是同一个锁
代码如下:

package com.gwh.lock.test;

/**
 * 同时访问静态Synchronized和非静态Synchronized方法
 */
public class SynchronizedStaticAndNormal8  implements  Runnable{
    public static SynchronizedStaticAndNormal8 staticAndNormal8=new SynchronizedStaticAndNormal8();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method1();
        }else {
            method2();
        }

    }

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

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

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(staticAndNormal8);
            Thread t2=new Thread(staticAndNormal8);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

结果如下:
在这里插入图片描述
7.方法抛出异常后,会释放锁
Synchronized修饰的类,抛出异常后会释放锁,lock类抛出异常后,不会释放锁
代码如下:

package com.gwh.lock.test;

/**
 * 方法抛出异常后,会释放锁。展示不抛出异常前,和抛出异常后的对比
 * 一旦抛出了异常,第二个线程会立刻进入同步方法,意味着锁已经释放
 */
public class SynchronizedException9 implements  Runnable{
    public static SynchronizedException9 exception9=new SynchronizedException9();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method1();
        }else {
            method2();
        }

    }

    public synchronized  void method1(){
        System.out.println("我是方法1,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
            throw new Exception();
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public synchronized void method2(){
        System.out.println("我是方法2,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行结束");
    }

    public static void main(String[] args) {
        try {
            Thread t1=new Thread(exception9);
            Thread t2=new Thread(exception9);
            t1.start();
            t2.start();
            while (t1.isAlive()||t2.isAlive()){

            }
            System.out.println("finished");

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}

结果如下: 在这里插入图片描述 总结: 1.一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待
2.每个实例都对应有自己的一把锁,不同实例之间互不影响;例外:锁对象是*.class以及Synchronized修饰的是static方法的时候,所有对象共用同一把类锁
3.无论是方法正常执行完毕或者是方法抛出异常,都会释放锁

问题:如果说,我在一个被Synchronized所修饰的方法中,访问一个不被Synchronized修饰的方法时,此时是线程安区的吗?
线程不安全,因为被访问的方法没有被Synchronized所修饰,所以他是会被多个线程共同访问的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值