多线程同步

synchronized的使用

一.同步的实现:利用锁对象来达到同步的效果,如下面的lock

//同步代码块
synchronized (lock){
  	for(int i=0;i<100;i++)
        System.out.println("第"+i+"次执行了方法");
}

二.当线程执行到这里时,就会使用这个锁对象,此时其他线程来到同步代码块,由于锁对象已经被使用了,就会进行等待,这样就达到了同步的效果,当第一个线程完成同步代码块,就会释放锁对象,此时其他线程才有机会进入

三.锁对象有三种:

  1. 自定义对象
  2. 当前类的this对象
  3. 类的Class对象,每一个类可以new多个对象,但是对应的Class对象只有一个
MyTest myTest1=new MyTest();
MyTest myTest2=new MyTest();
//结果为false,说明对象不相同
System.out.println(myTest1==myTest2); 
Class myTestClass1=MyTest.class;
Class myTestClass2=MyTest.class;
//结果为true,说明是同一个
System.out.println(myTestClass1==myTestClass2);
//自定义对象,obj就是自定义的
 static class SynchronizedTest{
  	  Object obj=new Object();
      public void print(String name){
          synchronized (obj){
              for(int i=0;i<100;i++)
                  System.out.println(name+"第"+i+"次执行了方法");
          }

      }
 }
//当前类的this对象
static class SynchronizedTest{
    public void print(String name){
        synchronized (this){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}
//类的class对象,用其他类的Class对象也可以
static class SynchronizedTest{
     public void print(String name){
         synchronized (SynchronizedTest.class){
             for(int i=0;i<100;i++)
                 System.out.println(name+"第"+i+"次执行了方法");
         }

     }
}

四.进行测试
推论:按第二步说的,线程进入就对锁对象进行使用,此时其他线程就无法进入,带着这个思路往下看

//这里不进行更改
static class MyThread extends Thread{

    SynchronizedTest synchronizedTest;

    public MyThread(String name,SynchronizedTest synchronizedTest) {
        super(name);
        this.synchronizedTest=synchronizedTest;
    }

    public void run(){
        synchronizedTest.print(super.getName());
    }
}
//第一次测试,自定义锁对象
public static void main(String[] agrs){
     SynchronizedTest synchronizedTest1=new SynchronizedTest();
     MyThread thread1=new MyThread("小明",synchronizedTest1);
     MyThread thread2=new MyThread("小王",synchronizedTest1);
     thread1.start();
     thread2.start();
}
//
static class SynchronizedTest{
	Object obj=new Object()
    public void print(String name){
        synchronized (obj){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

结果:小明先执行完,小王才可以开始
小明先拿到锁对象obj,执行完整个循环后退出了代码块,此时小王才可以开始
在这里插入图片描述

//第1-1测试(后面加的...)
//自定义锁对象,不同的是new了俩个SynchronizedTest对象
public static void main(String[] agrs){
     SynchronizedTest synchronizedTest1=new SynchronizedTest();
     SynchronizedTest synchronizedTest2=new SynchronizedTest();
     MyThread thread1=new MyThread("小明",synchronizedTest1);
     MyThread thread2=new MyThread("小王",synchronizedTest2);
     thread1.start();
     thread2.start();
}
//
static class SynchronizedTest{
	Object obj=new Object()
    public void print(String name){
        synchronized (obj){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

结果:小明没有执行完,小王就执行了
在这里插入图片描述

不同之处:第二次new了俩个SynchronizedTest对象,此时里面obj也会不相同

//第二次测试,Class锁对象
public static void main(String[] agrs){
     SynchronizedTest synchronizedTest1=new SynchronizedTest();
     MyThread thread1=new MyThread("小明",synchronizedTest1);
     MyThread thread2=new MyThread("小王",synchronizedTest1);
     thread1.start();
     thread2.start();
}
static class SynchronizedTest{
    public void print(String name){
        synchronized (SynchronizedTest.class){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

在这里插入图片描述

//第三次测试,Class锁对象,不同的是,new了俩个SynchronizedTest对象
 public static void main(String[] agrs){
      SynchronizedTest synchronizedTest1=new SynchronizedTest();
      SynchronizedTest synchronizedTest2=new SynchronizedTest();
      MyThread thread1=new MyThread("小明",synchronizedTest1);
      MyThread thread2=new MyThread("小王",synchronizedTest2);
      thread1.start();
      thread2.start();

 }
 //
static class SynchronizedTest{
    public void print(String name){
        synchronized (SynchronizedTest.class){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

在这里插入图片描述
俩次结果一样

猜想:虽然new了俩个SynchronizedTest ,但是里面的锁对象确实Class对象,也就是说锁对象使用的是同一个,所以才出现这个结果

不妨大胆假设:如果使用的锁对象是同一个,那么锁对象在被使用的情况下,其他线程就要等待。

//第四次测试,类的this对象,并且也new了俩个SynchronizedTest对象
public static void main(String[] agrs){
     SynchronizedTest synchronizedTest1=new SynchronizedTest();
     SynchronizedTest synchronizedTest2=new SynchronizedTest();
     MyThread thread1=new MyThread("小明",synchronizedTest1);
     MyThread thread2=new MyThread("小王",synchronizedTest2);
     thread1.start();
     thread2.start();

}
//
static class SynchronizedTest{
    public void print(String name){
        synchronized (this){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

结果:这次不是小明执行完后,小王才执行,好像符合我们的猜想,在这里插入图片描述

//第五次测试,类的this对象,下面只new了一个SynchronizedTest对象
public static void main(String[] agrs){
     SynchronizedTest synchronizedTest1=new SynchronizedTest();
     MyThread thread1=new MyThread("小明",synchronizedTest1);
     MyThread thread2=new MyThread("小王",synchronizedTest1);
     thread1.start();
     thread2.start();
}
//
static class SynchronizedTest{
    public void print(String name){
        synchronized (this){
            for(int i=0;i<100;i++)
                System.out.println(name+"第"+i+"次执行了方法");
        }

    }
}

结果:小明执行完了,小王才执行
在这里插入图片描述猜想:因为只new了一个,所以里面的this对象是同一个,所以同步代码块里一次只能进入一个线程

结论

:从这就可以断定了,只要锁对象使用同一个,就可以达到同步的效果

五、synchronized的其他用法

1.使用在普通方法上,此时synchronized的锁对象为当前类的this对象

public synchronized void print(String name){
    for(int i=0;i<100;i++)
        System.out.println(name+"第"+i+"次执行了方法");
}

2.使用在静态方法上,此时synchronized的锁对象为当前类的Class对象

static class SynchronizedTest{
    public static synchronized void print(String name){
        for(int i=0;i<100;i++)
            System.out.println(name+"第"+i+"次执行了方法");
    }
}

~~根据结论可以试着猜下结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值