synchronized 讀寫同步

synchronized 讀寫同步

這是一道面試題,不少人也遇到了。

要求:1.讀-讀 不用線程同步。2.讀-寫 要求線程同步,寫的時候不能讀。3.寫-寫同步。寫的時候不能寫。

java lock讀寫鎖是好的處理方案。這裏不說了。但人家問的是synchronized 讀寫同步。

假設兩個方法,write() ,read();
  1. read()之間不須要同步,正常的就行。
  2. read()與write()之間須要同步。
  3. 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();

    }

}

 

運行結果以下,經過結果分析,讀線程是穿插的,不存在同步。寫線程都是完整執行過程,是同步的。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 :開始寫的時候尚未讀完的線程。會致使錯誤。

-----待改進-----------

相關文章
相關標籤/搜索