java面试题6 牛客:哪个关键字可以对对象加互斥锁?
哪個關鍵字可以對對象加互斥鎖?()
A synchronized B volatile C serialize D staticsynchronized的4種用法
1.方法聲明時使用,放在范圍操作符(public等)之后,返回類型聲明(void等)之前.這時,線程獲得的是成員鎖,即一次只能有一個線程進入該方法,其他線程要想在此時調用該方法,只能排隊等候,當前線程(就是在synchronized方法內部的線程)執行完該方法后,別的線程才能進入.
public synchronized void synMethod() {//方法體}2.對某一代碼塊使用,synchronized后跟括號,括號里是變量,這樣,一次只有一個線程進入該代碼塊.此時,線程獲得的是成員鎖.例如:
public int synMethod(int a1){synchronized(a1) {//一次只能有一個線程進入}}??? 3.synchronized后面括號里是一對象,此時,線程獲得的是對象鎖.例如:
public class MyThread implements Runnable {public static void main(String args[]) {MyThread mt = new MyThread();Thread t1 = new Thread(mt, "t1");Thread t2 = new Thread(mt, "t2");Thread t3 = new Thread(mt, "t3");Thread t4 = new Thread(mt, "t4");Thread t5 = new Thread(mt, "t5");Thread t6 = new Thread(mt, "t6");t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();}public void run() {synchronized (this) {System.out.println(Thread.currentThread().getName());}} }對于3,如果線程進入,則得到當前對象鎖,那么別的線程在該類所有對象上的任何操作都不能進行.在對象級使用鎖通常是一種比較粗糙的方法。為什么要將整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只為了讓一個線程使用其中一部分資源,就將所有線程都鎖在外面。由于每個對象都有鎖,可以如下所示使用虛擬對象來上鎖:
class FineGrainLock {MyMemberClass x, y;Object xlock = new Object(), ylock = new Object();public void foo() {synchronized(xlock) {//access x here}//do something here - but don't use shared resourcessynchronized(ylock) {//access y here}}public void bar() {synchronized(this) {//access both x and y here}//do something here - but don't use shared resources}}4.synchronized后面括號里是類,此時,線程獲得的是對象鎖.例如:
class ArrayWithLockOrder{private static long num_locks = 0;private long lock_order;private int[] arr;public ArrayWithLockOrder(int[] a){arr = a;synchronized(ArrayWithLockOrder.class) {//-----這里num_locks++; // 鎖數加 1。lock_order = num_locks; // 為此對象實例設置唯一的 lock_order。}}public long lockOrder(){return lock_order;}public int[] array(){return arr;}}class SomeClass implements Runnable{public int sumArrays(ArrayWithLockOrder a1,ArrayWithLockOrder a2){int value = 0;ArrayWithLockOrder first = a1; // 保留數組引用的一個ArrayWithLockOrder last = a2; // 本地副本。int size = a1.array().length;if (size == a2.array().length){if (a1.lockOrder() > a2.lockOrder()) // 確定并設置對象的鎖定{ // 順序。first = a2;last = a1;}synchronized(first) { // 按正確的順序鎖定對象。synchronized(last) {int[] arr1 = a1.array();int[] arr2 = a2.array();for (int i=0; i<size; i++)value += arr1[i] + arr2[i];}}}return value;}public void run() {//}}對于4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對于含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖.
Volatile原理
Java語言提供了一種稍弱的同步機制,即volatile變量,用來確保將變量的更新操作通知到其他線程。當把變量聲明為volatile類型后,編譯器與運行時都會注意到這個變量是共享的,因此不會將該變量上的操作與其他內存操作一起重排序。volatile變量不會被緩存在寄存器或者對其他處理器不可見的地方,因此在讀取volatile類型的變量時總會返回最新寫入的值。
在訪問volatile變量時不會執行加鎖操作,因此也就不會使執行線程阻塞,因此volatile變量是一種比sychronized關鍵字更輕量級的同步機制。
當對非 volatile 變量進行讀寫的時候,每個線程先從內存拷貝變量到CPU緩存中。如果計算機有多個CPU,每個線程可能在不同的CPU上被處理,這意味著每個線程可以拷貝到不同的 CPU cache 中。
而聲明變量是 volatile 的,JVM 保證了每次讀變量都從內存中讀,跳過 CPU cache 這一步。
當一個變量定義為 volatile 之后,將具備兩種特性:
1.保證此變量對所有的線程的可見性,這里的“可見性”,如本文開頭所述,當一個線程修改了這個變量的值,volatile 保證了新值能立即同步到主內存,以及每次使用前立即從主內存刷新。但普通變量做不到這點,普通變量的值在線程間傳遞均需要通過主內存來完成。
2.禁止指令重排序優化。有volatile修飾的變量,賦值后多執行了一個“load addl $0x0, (%esp)”操作,這個操作相當于一個內存屏障(指令重排序時不能把后面的指令重排序到內存屏障之前的位置),只有一個CPU訪問內存時,并不需要內存屏障;(什么是指令重排序:是指CPU采用了允許將多條指令不按程序規定的順序分開發送給各相應電路單元處理)。
對象的串行化(Serialization)
一、串行化的概念和目的
1.什么是串行化
????????????對象的壽命通常隨著生成該對象的程序的終止而終止。有時候,可能需要將對象的狀態保存下來,在需要時再將對象恢復。我們把對象的這種能記錄自己的狀態以便將來再生的能力。叫作對象的持續性(persistence)。對象通過寫出描述自己狀態的數值來記錄自己 ,這個過程叫對象的串行化(Serialization) 。串行化的主要任務是寫出對象實例變量的數值。如果交量是另一對象的引用,則引用的對象也要串行化。這個過程是遞歸的,串行化可能要涉及一個復雜樹結構的單行化,包括原有對象、對象的對象、對象的對象的對象等等。對象所有權的層次結構稱為圖表(graph)。
2.串行化的目的
????????????Java對象的單行化的目標是為Java的運行環境提供一組特性,如下所示:
1)?????? 盡量保持對象串行化的簡單扼要 ,但要提供一種途徑使其可根據開發者的要求進行擴展或定制。
2)?????? 串行化機制應嚴格遵守Java的對象模型 。對象的串行化狀態中應該存有所有的關于種類的安全特性的信息。
3)?????? 對象的串行化機制應支持Java的對象持續性。
4)?????? 對象的串行化機制應有足夠的 可擴展能力以支持對象的遠程方法調用(RMI)。
5)?????? 對象串行化應允許對象定義自身 的格式即其自身的數據流表示形式,可外部化接口來完成這項功能。
二、串行化方法?
????????????從JDK1.1開始,Java語言提供了對象串行化機制 ,在java.io包中,接口Serialization用來作為實現對象串行化的工具 ,只有實現了Serialization的類的對象才可以被串行化。
????????????Serializable接口中沒有任何的方法。當一個類聲明要實現Serializable接口時,只是表明該類參加串行化協議,而不需要實現任何特殊的方法。下面我們通過實例介紹如何對對象進行串行化。
1.定義一個可串行化對象
????????????一個類,如果要使其對象可以被串行化,必須實現Serializable接口。我們定義一個類Student如下:
2.構造對象的輸入/輸出流
????????????要串行化一個對象,必須與一定的對象輸出/輸入流聯系起來,通過對象輸出流將對象狀態保存下來,再通過對象輸入流將對象狀態恢復。
????????????java.io包中,提供了ObjectInputStream和ObjectOutputStream將數據流功能擴展至可讀寫對象 。在ObjectInputStream 中用readObject()方法可以直接讀取一個對象,ObjectOutputStream中用writeObject()方法可以直接將對象保存到輸出流中。
運行結果
Student Info: ID:981036 Name:LiuMing Age:18 Dep:CSD?在這個例子中,我們首先定義了一個類Student,實現了Serializable接口 ,然后通過對象輸出流的writeObject()方法將Student對象保存到文件 data.ser中 。之后,通過對家輸入流的readObjcet()方法從文件data.ser中讀出保存下來的Student對象 。從運行結果可以看到,通過串行化機制,可以正確地保存和恢復對象的狀態。?
接著我們看看別人的評論
synchronized 關鍵字 : 用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多只有一個線程執行這個段代碼。
volatile:用來確保將變量的跟新操作通知到其他線程,當把變量聲明為volatile類型后,編譯器與運行時都會注意到這個變量是共享的,因此不會將該變量上的操作與其他內存操作一起重排序。然而,在訪問volatile變量時不會執行加鎖操作,因此也就不會使執行線程阻塞,因此volatile變量是一種比?synchronized關鍵字更輕量級的同步機制。
serialize:Java 對象序列化為二進制文件。
static關鍵字: static關鍵字可以修飾變量,方法,靜態代碼塊。
? ? ? ? ? ? ? ? ? ? ? ? ??靜態變量:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 由static修飾的變量稱為靜態變量
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 靜態變量屬于類,而不屬于某個對象
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??靜態變量它的副本只有一個(靜態變量在類中只加載一)
? ? ? ? ? ? ? ? ? ? ? ? ?靜態方法:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??在靜態方法中只能調用靜態變量和靜態方法
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 在非靜態方法中,可以調用靜態方法或者變量。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??在靜態方法中不能使用this和super關鍵字。
? ? ? ? ? ? ? ? ? ? ? ? 靜態代碼塊
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??作用:用來給靜態成員變量初始化
答案A
文章僅個人理解,來在各大網站。如有不合理之處,歡迎吐槽。
閱讀目錄(置頂)(長期更新計算機領域知識)https://blog.csdn.net/weixin_43392489/article/details/102380691
閱讀目錄(置頂)(長期更新計算機領域知識)https://blog.csdn.net/weixin_43392489/article/details/102380882
閱讀目錄(置頂)(長期科技領域知識)https://blog.csdn.net/weixin_43392489/article/details/102600114
歌謠帶你看java面試題 https://blog.csdn.net/weixin_43392489/article/details/102675944
總結
以上是生活随笔為你收集整理的java面试题6 牛客:哪个关键字可以对对象加互斥锁?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: skype api java版 打电话
- 下一篇: sql 避免除0错误_设计简历时避免这3