欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:Java之線程篇四

柚子快報激活碼778899分享:Java之線程篇四

http://yzkb.51969.com/

目錄

volatile關鍵字

volatile保證內存可見性

代碼示例

代碼示例2-(+volatile)

volatile不保證原子性

synchronized保證內存可見性

wait()和notify()

wait()方法

notify()

理解notify()和notifyAll()

wait和sleep的對比

volatile關鍵字

volatile保證內存可見性

volatile 修飾的變量, 能夠保證 "內存可見性".

代碼在寫入 volatile 修飾的變量的時候:

改變線程工作內存中volatile變量副本的值 將改變后的副本的值從工作內存刷新到主內存

代碼在讀取 volatile 修飾的變量的時候:?

從主內存中讀取volatile變量的最新值到線程的工作內存中 從工作內存中讀取volatile變量的副本?

加上 volatile , 強制讀寫內存. 速度是慢了, 但是數(shù)據變的更準確了。?

代碼示例

public class Demo13 {

private static int isQuit=0;

public static void main(String[] args) {

Thread t1=new Thread(()->{

while(isQuit==0){

}

System.out.println("t1 退出");

});

t1.start();

Thread t2=new Thread(()->{

System.out.println("請輸入 isQuit:");

Scanner scanner=new Scanner(System.in);

isQuit=scanner.nextInt();

});

t2.start();

}

}

運行結果

通過jconsole觀察,會看到線程t1處于RUNNABLE狀態(tài)。

t1

讀的是自己工作內存中的內容

.

t2

flag

變量進行修改

,

此時

t1

感知不到

flag

的變化

.

原因解釋:

1) load 讀取內存中isQuit的值到寄存器中. 2)通過cmp 指令比較寄存器的值是否是0.決定是否要繼續(xù)循環(huán). 由于這個循環(huán),循環(huán)速度飛快.短時間內,就會進行大量的循環(huán).也就是進行大量的load和cmp 操作.此時,編譯器/JVM就發(fā)現(xiàn)了,雖然進行了這么多次load,但是 load 出來的結果都一樣的.并且, load 操作又非常費時間,一次load花的時間相當于上萬次cmp 了. 所以編譯器就做了一個大膽的決定~~只是第一次循環(huán)的時候才讀了內存.后續(xù)都不再讀內存了,而是直接從寄存器中,取出isQuit的值了.?

代碼示例2-(+volatile)

public class Demo13 {

private static volatile int isQuit=0;

public static void main(String[] args) {

Thread t1=new Thread(()->{

while(isQuit==0){

}

System.out.println("t1 退出");

});

t1.start();

Thread t2=new Thread(()->{

System.out.println("請輸入 isQuit:");

Scanner scanner=new Scanner(System.in);

isQuit=scanner.nextInt();

});

t2.start();

}

}

運行結果

代碼示例3-(+sleep)

public class Demo13 {

private static int isQuit=0;

public static void main(String[] args) {

Thread t1=new Thread(()->{

while(isQuit==0){

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}

System.out.println("t1 退出");

});

t1.start();

Thread t2=new Thread(()->{

System.out.println("請輸入 isQuit:");

Scanner scanner=new Scanner(System.in);

isQuit=scanner.nextInt();

});

t2.start();

}

}

運行結果

volatile不保證原子性

代碼示例

class Counter {

volatile public int count = 0;

void increase() {

count++;

}

}

public class Demo13 {

public static void main(String[] args) throws InterruptedException {

final Counter counter = new Counter();

Thread t1 = new Thread(() -> {

for (int i = 0; i < 50000; i++) {

counter.increase();

}

});

Thread t2 = new Thread(() -> {

for (int i = 0; i < 50000; i++) {

counter.increase();

}

});

t1.start();

t2.start();

t1.join();

t2.join();

System.out.println(counter.count);

}

}

運行結果

我們會發(fā)現(xiàn),加上volatile以后,依舊不是線程安全的。

synchronized保證內存可見性

代碼示例

class Counter {

public int flag = 0;

}

public class Demo13 {

public static void main(String[] args) {

Counter counter = new Counter();

Thread t1 = new Thread(() -> {

while (true) {

synchronized (counter) {

if (counter.flag != 0) {

break;

}

}

}

System.out.println("循環(huán)結束!");

});

Thread t2 = new Thread(() -> {

Scanner scanner = new Scanner(System.in);

System.out.println("輸入一個整數(shù):");

counter.flag = scanner.nextInt();

});

t1.start();

t2.start();

}

}

運行結果

wait()和notify()

wait()方法

wait 做的事情:

使當前執(zhí)行代碼的線程進行等待. (把線程放到等待隊列中) 釋放當前的鎖 滿足一定條件時被喚醒, 重新嘗試獲取這個鎖.?

wait 要搭配 synchronized 來使用. 脫離 synchronized 使用 wait 會直接拋出異常.

代碼示例

public class Demo14 {

public static void main(String[] args) throws InterruptedException {

Object object = new Object();

synchronized (object) {

System.out.println("wait 之前");

// 把 wait 要放到 synchronized 里面來調用. 保證確實是拿到鎖了的.

object.wait();

System.out.println("wait 之后");

}

}

}

?運行結果

此時object就會一直進行wait,當然我們肯定不想讓程序一直等待下去,下面將介紹notify()來喚醒它。

notify()

notify 方法是喚醒等待的線程.?

方法notify()也要在同步方法或同步塊中調用,該方法是用來通知那些可能等待該對象的對象鎖的其它線程,對其發(fā)出通知notify,并使它們重新獲取該對象的對象鎖。 如果有多個線程等待,則有線程調度器隨機挑選出一個呈 wait 狀態(tài)的線程。(并沒有 "先來后到"),在notify()方法后,當前線程不會馬上釋放該對象鎖,要等到執(zhí)行notify()方法的線程將程序執(zhí)行完,也就是退出同步代碼塊之后才會釋放對象鎖。

代碼示例

public class Demo15 {

public static void main(String[] args) {

Object object = new Object();

Thread t1 = new Thread(() -> {

synchronized (object) {

System.out.println("wait 之前");

try {

object.wait();

// object.wait(5000);//也可以指定等待時間后自動喚醒

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

System.out.println("wait 之后");

}

});

Thread t2 = new Thread(() -> {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

synchronized (object) {

System.out.println("進行通知");

object.notify();

}

});

t1.start();

t2.start();

}

}

運行結果

notifyAll()

notify方法只是喚醒某一個等待線程. 使用notifyAll方法可以一次喚醒所有的等待線程.

代碼示例

class WaitTask implements Runnable {

private Object locker;

public WaitTask(Object locker) {

this.locker = locker;

}

@Override

public void run() {

synchronized (locker) {

while (true) {

try {

System.out.println("wait 開始");

locker.wait();

System.out.println("wait 結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

class NotifyTask implements Runnable {

private Object locker;

public NotifyTask(Object locker) {

this.locker = locker;

}

@Override

public void run() {

synchronized (locker) {

System.out.println("notify 開始");

locker.notifyAll();

System.out.println("notify 結束");

}

}

}

public class Demo16 {

public static void main(String[] args) throws InterruptedException {

Object locker = new Object();

Thread t1 = new Thread(new WaitTask(locker));

Thread t3 = new Thread(new WaitTask(locker));

Thread t4 = new Thread(new WaitTask(locker));

Thread t2 = new Thread(new NotifyTask(locker));

t1.start();

t2.start();

t3.start();

Thread.sleep(5000);

t4.start();

}

}

運行結果

注意: 雖然是同時喚醒 3 個線程, 但是這 3 個線程需要競爭鎖. 所以并不是同時執(zhí)行, 而仍然是有先有后的執(zhí)行.

理解notify()和notifyAll()

notify

只喚醒等待隊列中的一個線程

.

其他線程還是乖乖等著.

notifyAll 一下全都喚醒, 需要這些線程重新競爭鎖.

wait和sleep的對比

唯一的相同點就是都可以讓線程放棄執(zhí)行一段時間.

1. wait

需要搭配

synchronized

使用

. sleep

不需要

.

2. wait

Object

的方法

sleep

Thread

的靜態(tài)方法

.

柚子快報激活碼778899分享:Java之線程篇四

http://yzkb.51969.com/

精彩文章

評論可見,查看隱藏內容

本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19467358.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄