synchronized和Lock的区别是什么?
区别:1、lock是一个接口,而synchronized是java的一个关键字。2、synchronized在发生异常时会自动释放占有的锁,因此不会出现死锁;而lock发生异常时,不会主动释放占有的锁,必须手动来释放锁,可能引起死锁的发生。
在分布式开发中,锁是线程控制的重要途径。Java为此也提供了2种锁机制,synchronized和lock。
0、synchronized实现原理
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
普通同步方法,锁是当前实例对象
静态同步方法,锁是当前类的class对象
同步方法块,锁是括号里面的对象
当一个线程访问同步代码块时,它首先是需要得到锁,当退出或者抛出异常时必须要释放锁,那么它是如何来实现这个机制的呢?我们先看一段简单的代码:
package cn.alibab.javap;public class SynchronizedTest { public synchronized void test1(){ } public void test2(){ synchronized (this){ } } }
利用javap工具(javap是java编译之后的class文件的分解器)查看生成的class文件信息来分析Synchronized的实现
从上面可以看出,同步代码块是使用monitorenter和monitorexit指令实现的,同步方法(在这看不出来需要看JVM底层实现)依靠的是方法修饰符上的ACC_SYNCHRONIZED实现。
同步代码块:monitorenter指令是在编译后插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置,JVM需要保证每一个monitorenter都有一个monitorexit与之相对应。任何对象都有一个monitor与之相关联,当且一个monitor被持有之后,他将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor所有权,即尝试获取对象的锁;【摘自并发编程艺术】
同步方法:synchronized方法则会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令,在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Klass做为锁对象。(摘自:http://www.cnblogs.com/javaminer/p/3889023.html)
synchronized和lock的区别
区别如下:
来源:
lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;异常是否释放锁:
synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)是否响应中断
lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;是否知道获取锁
Lock可以通过trylock来知道有没有获取锁,而synchronized不能;Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度,
//Condition定义了等待/通知两种类型的方法 Lock lock=new ReentrantLock(); Condition condition=lock.newCondition();...condition.await();...condition.signal(); condition.signalAll();
1、synchronized和lock的用法区别
synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
lock:一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
2、synchronized和lock性能区别
synchronized是托管给JVM执行的,
而lock是java写的控制锁的代码。
在Java1.5中,synchronize是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。
但是到了Java1.6,发生了变化。synchronize在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地。
2种机制的具体区别:
synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。
现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
3、synchronized和lock用途区别
synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。
1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候
下面细细道来……
先说第一种情况,ReentrantLock的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。比如:如果A、B 2个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候ReentrantLock就提供了2种机制:可中断/可不中断
第一,B线程中断自己(或者别的线程中断它),但是ReentrantLock不去响应,继续让B线程等待,你再怎么中断,我全当耳边风(synchronized原语就是如此);
第二,B线程中断自己(或者别的线程中断它),ReentrantLock处理了这个中断,并且不再等待这个锁的到来,完全放弃。
更多编程相关知识,请访问:编程视频!!
Atas ialah kandungan terperinci synchronized和Lock的区别是什么?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

First,checkiftheFnkeysettingisinterferingbytryingboththevolumekeyaloneandFn volumekey,thentoggleFnLockwithFn Escifavailable.2.EnterBIOS/UEFIduringbootandenablefunctionkeysordisableHotkeyModetoensurevolumekeysarerecognized.3.Updateorreinstallaudiodriv

Testthepdfinanotherapptodetermineiftheisseiswiththefileoredge.2.enableTetHEBuilt-Inpdfviewerbyturningoff "AlwaysopenpdffileseXternally" dan "muat turun" inedgesettings.3.clearbrowsdataincludingcookiesandcookiescookiesandcookiescookiesandcookiescookieshincookieshincookiescookiescookiescookiescookiescookiescookiescookiescookiescokiescookiescookiescookiescookiescookiescooker

Modul pembalakan Python boleh menulis log ke fail melalui FileHandler. Pertama, hubungi pemproses dan format fail konfigurasi BasicConfig, seperti menetapkan tahap ke maklumat, menggunakan FileHandler untuk menulis app.log; Kedua, tambah StreamHandler untuk mencapai output ke konsol pada masa yang sama; Senario lanjutan boleh menggunakan timedrotatingfilehandler untuk membahagikan log mengikut masa, sebagai contoh, menetapkan apabila = 'tengah malam' untuk menghasilkan fail baru setiap hari dan menyimpan 7 hari sandaran, dan pastikan bahawa direktori log wujud; Adalah disyorkan untuk menggunakan getLogger (__ name__) untuk membuat pembalak bernama, dan menghasilkan

Menggunakan string.join () (java8) adalah kaedah yang paling mudah disyorkan untuk menyambungkan tatasusunan rentetan, hanya tentukan pemisah secara langsung; 2. Untuk versi lama Java atau apabila lebih banyak kawalan diperlukan, anda boleh menggunakan StringBuilder untuk secara manual melintasi dan bersembunyi; 3. Stringjoiner sesuai untuk senario yang memerlukan format yang lebih fleksibel seperti awalan dan akhiran; 4. Menggunakan Arrays.Stream () digabungkan dengan pengumpul.joining () sesuai untuk penapisan atau menukar array sebelum menyertai; Untuk meringkaskan, jika Java8 dan ke atas digunakan, kaedah string.join () harus lebih disukai dalam kebanyakan kes, yang ringkas dan mudah dibaca, tetapi untuk logik yang kompleks, ia disyorkan.

Menggunakan Pandasstyling dalam Jupyternotebook boleh mencapai paparan DataFrame yang indah. 1. Gunakan sorotan_max dan sorotan_min untuk menyerlahkan nilai maksimum (hijau) dan nilai minimum (merah) bagi setiap lajur; 2. Tambah warna latar belakang kecerunan (seperti blues atau merah) ke lajur angka melalui latar belakang_gradient untuk memaparkan saiz data secara visual; 3. Fungsi tersuai color_score digabungkan dengan applyMap untuk menetapkan warna teks untuk selang pecahan yang berbeza (≥90 hijau, 80 ~ 89 oren, 60 ~ 79 merah,

Dikira mempunyai cache, dan pelbagai akses tidak dikira semula apabila pergantungan tetap tidak berubah, sementara kaedah dilaksanakan setiap kali mereka dipanggil; 2. Komputed sesuai untuk pengiraan berdasarkan data responsif. Kaedah sesuai untuk senario di mana parameter diperlukan atau panggilan kerap tetapi hasilnya tidak bergantung kepada data responsif; 3. Kompted menyokong getters dan setters, yang dapat merealisasikan penyegerakan data dua hala, tetapi kaedah tidak disokong; 4. Ringkasan: Gunakan yang dikira terlebih dahulu untuk meningkatkan prestasi, dan menggunakan kaedah semasa lulus parameter, melakukan operasi atau mengelakkan cache, mengikuti prinsip "jika anda boleh menggunakan dikira, anda tidak menggunakan kaedah".

Jalankan proses kanak -kanak menggunakan pakej OS/EXEC, buat arahan melalui exec.command tetapi tidak melaksanakannya dengan segera; 2. Jalankan arahan dengan .Output () dan tangkap stdout. Jika kod keluar bukan sifar, kembalikan exec.exiterror; 3. Gunakan .start () untuk memulakan proses tanpa menyekat, menggabungkan dengan .stDoutPipe () untuk menstrimkan output dalam masa nyata; 4. Masukkan data ke dalam proses melalui .StDinPipe (), dan selepas menulis, anda perlu menutup saluran paip dan panggilan .Wait () untuk menunggu akhir; 5. EXEC.EXITError mesti diproses untuk mendapatkan kod keluar dan stderr perintah gagal untuk mengelakkan proses zombie.

Kaedah yang paling biasa ialah menggunakan os.path.isdir () atau pathlib.path.is_dir (). 1. Gunakan os.path.isdir (): importos, path = "/path/to/your/direktori", ifos.path.isdir (path): cetak ("ini direktori") lain: cetak ("Ini bukan direktori atau laluan tidak wujud"). 2. Gunakan pathlib.path.is_dir () (disyorkan): daripathlibImportp
