synchronized 讀寫同步
這是一道面試題,不少人也遇到了。
要求:1.讀-讀 不用線程同步。2.讀-寫 要求線程同步,寫的時候不能讀。3.寫-寫同步。寫的時候不能寫。
java lock讀寫鎖是好的處理方案。這裏不說了。但人家問的是synchronized 讀寫同步。
假設兩個方法,write() ,read();
1.和3.很好理解也很現實。
通過思考:write()必須是同步的,全部對象都要同步。那這裏須要設計成靜態的。若是不靜態的,保證每次同步都是一個鎖。
其次 read() 以前要栓查write同步鎖,但又沒有對應方法能夠檢查。想到的是 再寫一個栓查方法。這個方法與write使用同一個同步鎖(設計在同一個類,同時靜態)。但這個方法是空的,什麼也不作。
因此設計成以下代碼:
package test; public class Test { public void read() { canRead(); System.out.println(Thread.currentThread().getName() + "-->>begain read"); System.out.println(Thread.currentThread().getName() + "-->>reading"); try { Thread.sleep(1100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-->>read end"); } public static synchronized void canRead() { } public static synchronized void write() { System.out.println(Thread.currentThread().getName() + "-->>begain write"); canRead(); System.out.println(Thread.currentThread().getName() + "-->>writing"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-->>writing end"); return; } public static void main(String[] args) { Test test = new Test(); Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { test.read(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.setName("read_thread_1"); t.start(); Thread t1 = new Thread(new Runnable() { @Override public void run() { while (true) { test.read(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t1.setName("read_thread_2"); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } Test.write(); } } }); t2.setName("write_thread"); t2.start(); Thread t3 = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } Test.write(); } } }); t3.setName("write_thread_2"); t3.start(); } }
運行結果以下,經過結果分析,讀線程是穿插的,不存在同步。寫線程都是完整執行過程,是同步的。java
read_thread_1-->>begain read面試
read_thread_1-->>readingide
read_thread_2-->>begain read學習
read_thread_2-->>readingspa
read_thread_1-->>read end線程
read_thread_2-->>read end設計
read_thread_1-->>begain readcode
read_thread_1-->>reading對象
read_thread_2-->>begain readblog
read_thread_2-->>reading
read_thread_1-->>read end
read_thread_2-->>read end
write_thread-->>begain write
write_thread-->>writing
write_thread-->>writing end
read_thread_2-->>begain read
read_thread_2-->>reading
read_thread_1-->>begain read
read_thread_1-->>reading
write_thread_2-->>begain write
write_thread_2-->>writing
write_thread_2-->>writing end
read_thread_2-->>read end
read_thread_1-->>read end
read_thread_2-->>begain read
read_thread_2-->>reading
read_thread_1-->>begain read
read_thread_1-->>reading
read_thread_2-->>read end
read_thread_1-->>read end
write_thread-->>begain write
write_thread-->>writing
write_thread-->>writing end
write_thread_2-->>begain write
write_thread_2-->>writing
write_thread_2-->>writing end
read_thread_1-->>begain read
read_thread_1-->>reading
read_thread_2-->>begain read
read_thread_2-->>reading
read_thread_1-->>read end
read_thread_2-->>read end
read_thread_1-->>begain read
read_thread_1-->>reading
read_thread_2-->>begain read
read_thread_2-->>reading
write_thread-->>begain write
write_thread-->>writing
read_thread_1-->>read end
read_thread_2-->>read end
write_thread-->>writing end
write_thread_2-->>begain write
write_thread_2-->>writing
write_thread_2-->>writing end
read_thread_2-->>begain read
read_thread_2-->>reading
read_thread_1-->>begain read
read_thread_1-->>reading
read_thread_2-->>read end
read_thread_1-->>read end
read_thread_2-->>begain read
read_thread_1-->>begain read
read_thread_1-->>reading
read_thread_2-->>reading
write_thread-->>begain write
write_thread-->>writing
這個代碼冗餘部分是要執行一個空方法,目前尚未想到其它方法,有大牛有好辦法能夠留言互相學習。
代碼 bug :開始寫的時候尚未讀完的線程。會致使錯誤。
-----待改進-----------