Java中多執行緒的使用(超級超級詳細)執行緒安全+保證執行緒安全的三種方式 (同步代碼塊+同步方法+lock鎖) 5
當我們使用多執行緒訪問同一個資源時,且多個執行緒對資源有寫的 操作就容易出現執行緒安全問題,java為了解決執行緒安全問題引入了同步機制來解決,即在一個執行緒使用公共代碼塊的時候另一個執行緒不可以使用
下面我用一個搶票的案例來給大家講解保證執行緒安全的幾種方式
首先我們先來看看沒有使用鎖的情況下出現的情況
package ThreadSafe;
public class ThreadSafe implements Runnable {
//定義一個多執行緒共享的 票源
private int ticketsum=100;
//設定買票的執行緒任務
public void run(){
while(true) {
//判斷還有沒有票
if (ticketsum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在賣:" + ticketsum);
ticketsum--;
}
}
}
}
package ThreadSafe;
public class Main {
public static void main(String[] args) {
//創建Runable實作物件
ThreadSafe threadSafe = new ThreadSafe();
//創建Thread類物件
Thread one = new Thread(threadSafe, "一號");
Thread two = new Thread(threadSafe, "二號");
Thread three = new Thread(threadSafe, "三號");
one.start();
two.start();
three.start();
}
}
出現的問題
出現負數的票與重復票

對于執行緒安全原理不懂的兄弟可以去看看我的另一篇文章
鏈接:https://blog.csdn.net/pjh88/article/details/107359745
下面演示加鎖的情況
方法一:同步代碼塊
同步代碼塊:synchronized關鍵字可以用于某個區塊中,表示對這個區塊的資源實行互斥訪問
synchronized(同步鎖){
需要同步操作的代碼
}
同步鎖:
物件的同步鎖只是一個概念,可以想象為在改物件上上了一把鎖
1.鎖可以是任意的型別
2.多個執行緒物件要使用同一把鎖
任何時候都最多允許一個物件擁有同步鎖誰拿到鎖就誰進入同步代碼塊
使用以下代碼塊來演示
package ThreadSafe;
public class Main {
public static void main(String[] args) {
//創建Runable實作物件
ThreadSafe threadSafe = new ThreadSafe();
//創建Thread類物件
Thread one = new Thread(threadSafe, "一號");
Thread two = new Thread(threadSafe, "二號");
Thread three = new Thread(threadSafe, "三號");
one.start();
two.start();
three.start();
}
}
package ThreadSafe;
public class ThreadSafe implements Runnable {
//定義一個多執行緒共享的 票源
private int ticketsum=100;
java.lang.Object object=new java.lang.Object();
//設定買票的執行緒任務
public void run(){
while(true) {
synchronized (object){
//判斷還有沒有票
if (ticketsum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在賣:" + ticketsum);
ticketsum--;
}
}
}
}
}
結果
可以發現沒有執行緒不安全的情況出現

同步代碼塊原理決議:

同步方法
什么是同步方法?
使用synchronized修飾的方法叫做同步方法,保證執行緒安全,當a執行緒執行該方法的時候,其他執行緒只可以在方法外等待
public synchornized void method(){
可能產生執行緒安全的代碼塊
}
那么鎖物件在哪呢?
鎖物件是隱藏的,誰呼叫這個方法誰就是隱藏的鎖物件,
對于非static方法鎖物件就是this
對于static方法鎖物件是類名.class
上代碼
package ThreadSafe;
public class ThreadSafe implements Runnable {
//定義一個多執行緒共享的 票源
private int ticketsum=100;
java.lang.Object object=new java.lang.Object();
//設定買票的執行緒任務
public void run(){
while(true) {
shuchu();
}
}
public synchronized void shuchu(){
//判斷還有沒有票
if (ticketsum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在賣:" + ticketsum);
ticketsum--;
}
}
}
package ThreadSafe;
public class Main {
public static void main(String[] args) {
//創建Runable實作物件
ThreadSafe threadSafe = new ThreadSafe();
//創建Thread類物件
Thread one = new Thread(threadSafe, "一號");
Thread two = new Thread(threadSafe, "二號");
Thread three = new Thread(threadSafe, "三號");
one.start();
two.start();
three.start();
}
}
結果
由結果可以看出沒有出現執行緒安全的問題

另一種實作方法
上代碼
package ThreadSafe;
public class ThreadSafe implements Runnable {
//定義一個多執行緒共享的 票源
private int ticketsum=100;
java.lang.Object object=new java.lang.Object();
//設定買票的執行緒任務
public void run(){
while(true) {
shuchu();
}
}
public void shuchu(){
synchronized(this) {
//判斷還有沒有票
if (ticketsum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在賣:" + ticketsum);
ticketsum--;
}
}
}
}
package ThreadSafe;
public class Main {
public static void main(String[] args) {
//創建Runable實作物件
ThreadSafe threadSafe = new ThreadSafe();
//創建Thread類物件
Thread one = new Thread(threadSafe, "一號");
Thread two = new Thread(threadSafe, "二號");
Thread three = new Thread(threadSafe, "三號");
one.start();
two.start();
three.start();
}
}
所得的結果和上面是一樣的
Lock鎖
java.util.concurrent.locks.Lock 機制提供了比synchronized代碼塊和synchronized方法更廣泛的鎖定操作, 同步代碼塊/同步方法具有的功能Lock都有,除此之外更強大,更體現面向物件,
Lock鎖的功能
public void lock()加同步鎖
public void unlock() 釋放同步鎖
下面使用一段代碼演示
package ThreadSafe;
public class Main {
public static void main(String[] args) {
//創建Runable實作物件
ThreadSafe threadSafe = new ThreadSafe();
//創建Thread類物件
Thread one = new Thread(threadSafe, "一號");
Thread two = new Thread(threadSafe, "二號");
Thread three = new Thread(threadSafe, "三號");
one.start();
two.start();
three.start();
}
}
package ThreadSafe;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadSafe implements Runnable {
//定義一個多執行緒共享的 票源
private int ticketsum=100;
ReentrantLock lock=new ReentrantLock();
//設定買票的執行緒任務
public void run(){
while(true) {
shuchu();
}
}
public void shuchu(){
while (true){
lock.lock();
//判斷還有沒有票
if (ticketsum > 0) {
try {
Thread.sleep(10);
String name = Thread.currentThread().getName();
System.out.println(name + "正在賣:" + ticketsum);
ticketsum--;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
}
以上就是java鎖的一些基本知識,如有錯誤還請各位批評指正,喜歡我的文章的可以關注我,也可以點贊收藏支持一下

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/141645.html
標籤:Java
