当前位置: 首页 > 后端技术 > Java

Synchronized在Java中的用法(简介)

时间:2023-04-01 16:17:48 Java

Java中Synchronized的用法(简介)简介Synchronized是Java中的关键字,是同步锁的一种。它修饰的对象如下:  1。修改代码块。修改后的代码块称为同步语句块。它的作用范围是花括号{}括起来的代码。代码块的对象;  2.修改一个方法,被修改的方法称为同步方法,它的作用范围是整个方法,作用对象是调用这个方法的对象;  3.方法,它的作用范围是整个静态方法,作用对象是这个类的所有对象;  4.修改一个类,其作用范围是synchronized后括号内的部分,作用的主要对象是所有对象中的这个类。装饰一个密码块  1。当一个线程访问对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。 示例:查看代码使用关键字synchronized来运行结果。不使用关键字synchronized来运行结果。当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码块时,只能有一个线程执行,另一个线程阻塞,必须在当前线程执行完后才执行代码块代码块。Thread1和thread2是互斥的,因为synchronized代码块执行时会锁定当前对象,只有代码块执行完才能释放对象锁,下一个线程才能执行并锁定对象。让我们稍微改变一下SyncThread的调用:线程thread1=newThread(newSyncThread(),"SyncThread1");线程thread2=newThread(newSyncThread(),"SyncThread2");thread1.start();thread2.start();}复制代码运行结果为什么上面例子中的thread1是和thread2同时执行的。这是因为synchronized只对对象加锁,每个对象只有一个锁(lock)与之关联,上面的代码相当于下面的代码:println("newSyncThread()foreachcallusingthekeywordsynchronized");SyncThreadsyncThread1=newSyncThread();SyncThreadsyncThread2=newSyncThread();线程thread1=newThread(syncThread1,"SyncThread1");线程thread2=newThread(syncThread2,"SyncThread2");thread1.start();thread2.start();}复制代码此时创建了两个SyncThread对象syncThread1和syncThread2,线程thread1执行syncThread1对象中的同步代码(run),线程thread2执行syncThread1对象中的同步代码(run)syncThread2对象;我们知道synchronized是给对象加锁的,那么就会有两把锁分别给syncThread1对象和syncThread2对象加锁,而且这两把锁是不互斥的。相互干扰,不形成互斥,所以两个线程可以同时执行。2.当一个线程访问对象的synchronized(this)同步代码块时,另一个线程仍然可以访问对象中的non-synchronized(this)同步代码块。多线程访问同步和非同步代码块    查看代码运行结果  以上代码中countAdd是同步的,printCount是非同步的。从上面的结果可以看出,当一个线程访问一个对象的synchronized代码块时,其他线程可以访问该对象的非synchronized代码块而不会被阻塞。修改方法Synchronized修改方法很简单,就是在方法前面加上synchronized,publicsynchronizedvoidmethod(){};synchronized修改方法类似于修改一个代码块,但是作用范围不同,被修改的代码块用花括号括起来,方法的作用域向上,被修改方法的作用域是整个函数。如果把run方法改成下面的方法,效果是一样的。复制代码publicsynchronizedvoidrun(){{for(inti=0;i<5;i++){try{System.out.println("线程名称:"+Thread.currentThread().getName()+":"+(计数++));线程.睡眠(100);}catch(InterruptedExceptione){e.printStackTrace();}}}}复制代码运行结果Synchronized作用于整个方法。写法一:publicsynchronizedvoidmethod(){//todo}写法二:复制代码publicvoidmethod(){synchronized(this){}}复制代码写法一修改一个方法,写法二修改一个代码block,但是写法1和写法2是等价的,都是锁住整个方法的内容。用synchronized修饰方法要注意以下几点:synchronized关键字不能被继承。虽然可以使用synchronized来定义方法,但是synchronized并不是方法定义的一部分,因此不能继承synchronized关键字。如果父类中的某个方法使用了synchronized关键字,在子类中重写了这个方法,那么子类中的方法默认是不同步的,必须在子类中显式指定。将synchronized关键字添加到方法中。当然也可以在子类的方法中调用父类中对应的方法,这样虽然子类中的方法没有同步,但是子类调用了父类的同步方法,所以子类的方法是等价的同步起来。这两个方法的示例代码如下:在子类方法中加入synchronized关键字复制代码codein在子类方法中调用父类的同步方法复制代码}}定义接口方法时复制代码不能使用synchronized关键字。构造函数不能使用synchronized关键字,但可以使用synchronized代码块进行同步。修改静态方法Synchronized也可以修改静态方法,用法如下:publicsynchronizedstaticvoidmethod(){}我们知道静态方法属于类,不属于对象。同理,synchronized修饰的静态方法会锁住该类的所有对象。synchronized修饰的静态方法查看代码运行结果syncThread1和syncThread2是SyncThread的两个对象,但是在thread1和thread2并发执行时保持线程同步。这是因为在run中调用的是静态方法method,而静态方法属于类,所以syncThread1和syncThread2相当于使用了同一个锁。这与使用关键字synchronized修饰类的结果是一样的。同步也可以用在一个类上。使用方法如下:ViewCode运行结果的效果和上面synchronized修饰的静态方法是一样的。当synchronized作用于一个类T时,就是为这个类T加锁,T的所有对象都使用同一个锁。总结:1、不管synchronized关键字是加在方法上还是加在对象上,如果它作用的对象是非静态的,那么它获取的锁就是对象;如果synchronized作用的对象是一个静态方法或者一个类,那么它获得的锁就是一对类,这个类的所有对象都拥有同一个锁。2、每个对象只有一把锁(lock)与之关联,谁得到了锁,谁就可以运行它所控制的代码。3.实现同步需要大量的系统开销作为代价,甚至可能造成死锁,所以尽量避免不必要的同步控制