Java馬士兵高並發編程視頻學習筆記(一)


1.同一個資源,同步和非同步的方法可以同時調用

復制代碼
package com.dingyu;

public class Y {
public synchronized void m1() {
System.out.println(Thread.currentThread().getName()
+ " m1 begin---------");
try {
Thread.sleep(
5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ " m1 end---------");
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() {
    System.out.println(Thread.currentThread().getName() </span>+ " m2 begin---------"<span style="color: #000000;">);
    </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>5000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        </span><span style="color: #008000;">//</span><span style="color: #008000;"> TODO Auto-generated catch block</span>

e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ " m2 end---------");
}
public static void main(String[] args) {
Y t
= new Y();
// new Thread(()->t.m1(),"t1").start();
// new Thread(()->t.m2(),"t2").start();
new Thread(new Runnable() {

        @Override
        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> run() {
            t.m1();
            
        }
    },</span>"t1"<span style="color: #000000;">).start();;
</span><span style="color: #0000ff;">new</span> Thread(<span style="color: #0000ff;">new</span><span style="color: #000000;"> Runnable() {
        
        @Override
        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> run() {
            t.m2();
            
        }
    },</span>"t2"<span style="color: #000000;">).start();;
}

}

復制代碼

 

 

可以看到t1先執行,如果不能同時調用那么t2是不能執行的,必須等t1結束,釋放鎖后才能調用,但這里t2確先執行了,所以是可以同時調用的。

2.對業務寫代碼進行加鎖,對讀代碼不進行加鎖,會產生臟讀

  

復制代碼
package com.dingyu;

public class U {
private String name;
private double banlance;

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> set(String name, <span style="color: #0000ff;">double</span><span style="color: #000000;"> balance) {
    </span><span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;
    </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>5000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        e.printStackTrace();
    }
    </span><span style="color: #0000ff;">this</span>.banlance =<span style="color: #000000;"> balance;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">double</span><span style="color: #000000;"> getBalance() {
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> banlance;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    U u </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> U();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt; u.set("zhangsan", 500<span style="color: #000000;">)).start();
    System.out.println(u.getBalance());
    </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>5000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(u.getBalance());
}

}

復制代碼

3.同線程內一個同步方法可以去調用另一個同步方法(重入鎖 還有一種重入鎖就是子類調用父類的同步方法)

復制代碼
package com.dingyu;

public class I {
public synchronized void m1() {
System.out.println(
"m1 start");
m2();
System.out.println(
"m1 end");
}

</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() {
    System.out.println(</span>"m2 start"<span style="color: #000000;">);
    System.out.println(</span>"m2 end"<span style="color: #000000;">);
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    I i </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> I();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt;<span style="color: #000000;"> i.m1()).start();
}

}

復制代碼

4.模擬一個簡單的死鎖

復制代碼
package com.dingyu;

public class DeadLock {
private Object o1 = new Object();
private Object o2 = new Object();

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (o1) {
        </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
            Thread.sleep(</span>10000<span style="color: #000000;">);
        } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
            e.printStackTrace();
        }
        
        </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (o2) {
            System.out.println(</span>"如果出現這句話表示沒有死鎖"<span style="color: #000000;">);
        }
    }
    
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">(o2) {
        
        </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (o1) {
            System.out.println(</span>"如果出現這句話表示沒有死鎖"<span style="color: #000000;">);
        }
        
    }
    
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    DeadLock deadLock</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> DeadLock();
    </span><span style="color: #0000ff;">new</span> Thread(()-&gt;<span style="color: #000000;">deadLock.m1()).start();
    </span><span style="color: #0000ff;">new</span> Thread(()-&gt;<span style="color: #000000;">deadLock.m2()).start();
}

}

復制代碼

5.如果執行同步方法中出現異常,那么就會自動釋放鎖,如果不想釋放鎖,加上try catch

復制代碼
package com.dingyu;

public class ReleaseLock {
private int count = 0;
private int i = 0;

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</span><span style="color: #000000;">) {
        System.out.println(Thread.currentThread().getName() </span>+ " " + count++<span style="color: #000000;">);
        </span><span style="color: #0000ff;">if</span> (count % 10 == 0<span style="color: #000000;">)
            i </span>= 1 / 0<span style="color: #000000;">;
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    ReleaseLock releaseLock </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReleaseLock();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt; releaseLock.m1(), "t1"<span style="color: #000000;">).start();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt; releaseLock.m1(), "t2"<span style="color: #000000;">).start();
}

}

復制代碼

 6.volatile關鍵字(無鎖同步)

volatile關鍵字 每個線程都有自己的一小塊內存,執行的時候會把變量copy過來,修改了后在寫回對象,

執行m1方法的線程把 running讀到內存里,與此同時主線程也把running讀到內存,並進行修改,寫回對象為false

但是執行m1的線程里的內存一直都是true啊(因為太忙了沒空去刷新)所以會形成死循環,

volatile就是當running改了之后 *立馬去通知其他線程,你們記得去主存刷新一下,一刷新,running為false,退出while循環。

復制代碼
package com.dingyu;
/**
 * volatile關鍵字   每個線程都有自己的一小塊內存,執行的時候會把變量copy過來,修改了后在寫回對象,
 * 執行m1方法的線程把 running讀到內存里,與此同時主線程也把running讀到內存,並進行修改,寫回對象為false
 * 但是執行m1的線程里的內存一直都是true啊(因為太忙了沒空去刷新)所以會形成死循環,volatile就是當running改了之后
 * 立馬去通知其他線程,你們記得去主存刷新一下,一刷新,running為false,退出while循環。
 * @author dingyu
 *
 */
public class VolatileDemo {
    private volatile boolean running = true;
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    System.out.println(</span>"m1 start"<span style="color: #000000;">);
    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (running) {
        
    }
    System.out.println(</span>"m1 end"<span style="color: #000000;">);
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    VolatileDemo volatileDemo </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> VolatileDemo();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt;<span style="color: #000000;"> volatileDemo.m1()).start();
    </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>1000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        e.printStackTrace();
    }
    volatileDemo.running </span>= <span style="color: #0000ff;">false</span><span style="color: #000000;">;

}

}

復制代碼

7.voliatile 不能保證原子性 不能替換synchronized

復制代碼
package com.dingyu;

/**

  • voliatile 不能保證原子性 不能替換synchronized
  • @author dingyu

*/
public class VolatileDemo02 {
public volatile int count = 0;

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i &lt;= 10000; i++<span style="color: #000000;">)
        count</span>++<span style="color: #000000;">;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    VolatileDemo02 volatileDemo02 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> VolatileDemo02();
    </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i &lt; 3; i++<span style="color: #000000;">) {
        </span><span style="color: #0000ff;">new</span> Thread(() -&gt;<span style="color: #000000;"> volatileDemo02.m1()).start();
    }
    </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>5000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(volatileDemo02.count);
}

}

復制代碼

 8.多個原子類的方法之間不具備原子性

復制代碼
package com.dingyu;

import java.util.concurrent.atomic.AtomicInteger;

/**

  • 原子類 具有原子性,但兩個原子類的方法之間不具備原子性
  • @author dingyu

*/
public class AtomicDemo {
private AtomicInteger count = new AtomicInteger();

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i &lt; 100; i++<span style="color: #000000;">) {            
        count.incrementAndGet();
        </span><span style="color: #008000;">//</span><span style="color: #008000;">兩個原子類的方法之間不具備原子性</span>

count.incrementAndGet();

    }
}

}

復制代碼

9.原子類的不具備可見性

復制代碼
package com.dingyu;

import java.util.concurrent.atomic.AtomicBoolean;

public class AtomicDemo02 {
public AtomicBoolean running = new AtomicBoolean(true);

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (running.get()) {

    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    AtomicDemo02 demo02 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> AtomicDemo02();
    </span><span style="color: #0000ff;">new</span> Thread(()-&gt;<span style="color: #000000;">demo02.m1()).start();
    demo02.running.set(</span><span style="color: #0000ff;">false</span><span style="color: #000000;">);
}

}

復制代碼

10.鎖是鎖在堆內存的那個對象上,而不是引用

復制代碼
package com.dingyu;

/**

  • 鎖是鎖在堆內存的那個對象上,而不是引用
  • @author dingyu

*/
public class ChangeReference {
public Object o = new Object();

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #008000;">//</span><span style="color: #008000;">鎖o</span>
    <span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (o) {
        </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</span><span style="color: #000000;">) {
            </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
                Thread.sleep(</span>1000<span style="color: #000000;">);
            } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    ChangeReference changeReference </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ChangeReference();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt; changeReference.m1(), "t1").start();<span style="color: #008000;">//</span><span style="color: #008000;">啟動一個線程 叫t1</span>
    <span style="color: #0000ff;">try</span><span style="color: #000000;"> {
        Thread.sleep(</span>3000<span style="color: #000000;">);
    } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
        e.printStackTrace();
    }
    changeReference.o </span>= <span style="color: #0000ff;">new</span> Object();<span style="color: #008000;">//</span><span style="color: #008000;">引用變了</span>
    <span style="color: #0000ff;">new</span> Thread(() -&gt; changeReference.m1(),"t2").start();<span style="color: #008000;">//</span><span style="color: #008000;">啟動線程 t2</span>

}
}

復制代碼

 

 11.不要鎖字符串常量

復制代碼
package com.dingyu;
/**
 * 不要鎖字符串常量
 * @author dingyu
 *
 */
public class SynchronizedString {
    private String s1 = "hello";
    private String s2 = "hello";
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (s1) {
        </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) {}
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (s2) {
        System.out.println(</span>"m2 start"<span style="color: #000000;">);
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    SynchronizedString synchronizedString </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> SynchronizedString();
    </span><span style="color: #0000ff;">new</span> Thread(()-&gt;<span style="color: #000000;">synchronizedString.m1()).start();
    </span><span style="color: #0000ff;">new</span> Thread(()-&gt;<span style="color: #000000;">synchronizedString.m2()).start();
}

}

復制代碼

12.wait 讓線程暫停,釋放鎖, notify 喚醒線程,不釋放鎖

復制代碼
package com.dingyu2;

/**

  • wait 讓線程暫停,釋放鎖, notify 喚醒線程,不釋放鎖
  • @author dingyu

*/
public class WaitAndNotyifyDemo {
private volatile int count = 0;
private Object lock = new Object();

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (lock) {
        System.out.println(</span>"m1 start"<span style="color: #000000;">);
        </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i &lt; 10; i++<span style="color: #000000;">) {
            count</span>++<span style="color: #000000;">;
            System.out.println(count);
            </span><span style="color: #0000ff;">if</span> (count == 5<span style="color: #000000;">) {
                lock.notify();
                </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
                    lock.wait();
                } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() {
    </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> (lock) {
        System.out.println(</span>"m2 start"<span style="color: #000000;">);
        </span><span style="color: #0000ff;">if</span> (count != 5<span style="color: #000000;">) {
            </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
                System.out.println(</span>"m2 在等着 但把鎖釋放了"<span style="color: #000000;">);
                lock.wait();                    
            } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(</span>"m2 end"<span style="color: #000000;">);
        lock.notify();
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    WaitAndNotyifyDemo waitAndNotyifyDemo </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> WaitAndNotyifyDemo();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt;<span style="color: #000000;"> waitAndNotyifyDemo.m2()).start();
    </span><span style="color: #0000ff;">new</span> Thread(() -&gt;<span style="color: #000000;"> waitAndNotyifyDemo.m1()).start();
}

}

復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM