synchronized 读写同步
这是一道面试题,很多人也遇到了。
要求:1.读-读 不用线程同步。2.读-写 要求线程同步,写的时候不能读。3.写-写同步。写的时候不能写。
java lock读写锁是好的处理方案。这里不说了。但人家问的是synchronized 读写同步。
假设两个方法,write() ,read();
- read()之间不需要同步,正常的就行。
- read()与write()之间需要同步。
- write()之间需要同步。
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(); } }
运行结果如下,通过结果分析,读线程是穿插的,不存在同步。写线程都是完整执行过程,是同步的。
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
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 :开始写的时候还没有读完的线程。会导致错误。
-----待改进-----------