synchronized关键字的作用是什么,最准确描述synchronized关键字

  synchronized关键字的作用是什么,最准确描述synchronized关键字

  Synchronized关键字是java并发编程中常用的同步锁,用于锁定方法或代码块。锁定代码块时,可以是synchronized(this){},synchronized(Object){},synchronized (class){}。

  如何解决写爬虫IP受阻的问题?立即使用。

  当锁定的内容结束或在执行过程中抛出异常时,锁将被自动释放。

  如果要手动释放锁,需要调用被锁定对象的wait()方法来释放锁并使其处于等待状态,切换到其他线程。notify()方法只唤醒另一个调用对象wait()方法的线程,但不会释放锁,选择顺序不受代码控制,由虚拟机实现。

  因此,对象的wait()、notify()和notifyAll()方法只能与synchronized关键字一起使用,以完成线程间的调度。

  其中锁定方法相当于同步(this){方法的所有代码作为代码块},如下所示:

  公共同步void测试(){

  .

  }相当于

  公共无效测试(){

  同步(这){

  .

  }

  }上面的例子锁定了这个类的对象。如果锁定的方法是静态方法,我们知道静态方法属于类而不是对象。因此,同步修改的静态方法锁定该类的所有对象,也就是说,即使是两个实例对象,只要都是该类,也会被锁定。

  公共同步静态void测试(){

  .

  }相当于

  公共静态void测试(){

  同步(类。类){

  .

  }

  }不管是锁方法还是代码块,不管锁代码块时引用的对象是什么,只要记住一个原则就一目了然了,就是引用对象相同时,同步锁才会起作用,否则锁不会互斥,可以并发执行。

  Synchronized(this)表示当当前类的对象实例相同时锁起作用,synchronized(Object)表示当对象对象相同时锁起作用,synchronized (class class)表示当它们都是这个类时锁起作用。

  举个简单的例子:

  公共类TestController {

  公共类任务实现Runnable{

  私有字符串str

  任务(字符串)

  this.str=str

  }

  @覆盖

  公共无效运行(){

  同步(字符串){

  尝试{

  thread . sleep(3000 l);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  system . out . println(str);

  }

  }

  }

  公共静态void main(String[] args)引发InterruptedException {

  test controller test controller=new test controller();

  Thread thread1=新线程(test controller . new Task( 1 ));

  Thread thread2=新线程(test controller . new Task( 1 ));

  thread 1 . start();

  thread 2 . start();

  }

  }在上面的代码中,引用对象str是‘1’。在java中,如果字符串String由this.str=1 赋值,则等效于str=String.valueOf(1 )。如果字符串 1 之前已经初始化过,它会直接取前一个,所以是同一个对象。根据上面介绍的原理,锁会起作用,所以结果是3秒后输出1,3秒后再输出1。

  如果将thread2改为

  Thread thread2=新线程(test controller . new Task( 2 ));此时参考对象一个是 1 ,一个是 2 ,不是同一个对象,所以锁不会互斥,不会起作用,所以结果是3秒后1和2几乎同时输出。

  以上都是多线程同时调用同一个方法。如果调用不同的方法呢?

  公共类测试{

  公共同步void m1(){

  System.out.println(m1正在运行.);

  尝试{

  thread . sleep(3000 l);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  system . out . println(“m1 end”);

  }

  公共同步void m2(){

  System.out.println(m2正在运行.);

  system . out . println(“m2 end”);

  }

  公共静态void main(String[] args) {

  测试Test=new Test();

  新线程(新Runnable() {

  @覆盖

  公共无效运行(){

  test . m1();

  }

  }).start();

  新线程(新Runnable() {

  @覆盖

  公共无效运行(){

  test . m2();

  }

  }).start();

  }

  }上面代码的输出结果是:

  m1运行.

  //3秒钟后

  m1端

  m2运行.

  M2在上面说过,synchronized modification相当于synchronized(this){将方法的所有代码作为一个代码块},this代表成为一个对象。也就是说,第一个线程获得测试对象的锁。因为所有的对象都是相同的测试,所以第二个线程不能获得锁并被阻塞。

  将上述示例转换为以下内容:

  私有字符串str= 1

  公共void m1(){

  同步(字符串){

  System.out.println(m1正在运行.);

  尝试{

  thread . sleep(3000 l);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  system . out . println(“m1 end”);

  }

  }

  公共void m2(){

  同步(字符串){

  System.out.println(m2正在运行.);

  system . out . println(“m2 end”);

  }

  }第一个线程调用m1()时,获取对象str的锁,第二个线程调用m2()时,也需要获取对象str的锁。而且因为是同一个测试对象,所以两个str是同一个对象,所以第二个线程会因为拿不到锁而被阻塞。输出结果与前面的示例相同。

  如果上面的例子修改如下:

  公共类M1 {

  public void m(String str){

  同步(字符串){

  system . out . println( m1 running );

  尝试{

  thread . sleep(3000 l);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  system . out . println(“m1 end”);

  }

  }

  }

  公共类M2 {

  public void m(String str){

  同步(字符串){

  system . out . println( m2 runing );

  system . out . println(“m2 end”);

  }

  }

  }

  公共类测试{

  公共静态void main(String[] args) {

  String str= 1

  新线程(新Runnable() {

  @覆盖

  公共无效运行(){

  新M1()。m(str);

  }

  }).start();

  新线程(新Runnable() {

  @覆盖

  公共无效运行(){

  新M2()。m(str);

  }

  }).start();

  }

  }这个调用的方法在两个类中,但是结果和前面两个例子一样,因为传入的都是锁定的str对象,同一个对象只有一个锁。第一个线程拿,第二个线程只能等。

  总结:

  A.无论synchronized关键字添加到方法还是对象,如果它作用的对象是非静态的,那么它获取的锁就是对象;如果同步的对象是一个静态方法或类,它获得的锁是一对类,并且该类的所有对象都有相同的锁。

  B.每个对象只有一个与之关联的锁,获得这个锁的人可以运行它所控制的代码。

  C.实现同步需要耗费大量的系统开销,甚至可能造成死锁,所以尽量避免不必要的同步控制。以上是同步关键词使用的详细内容。请多关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: