線程同步的機制是用來解決線程安全問題的
操作同步代碼時,只能有一個線程參與,其他線程等待。相當於是一個單線程的過程,效率低。
標題1、Java中同步機制有一下幾種方式
1.1、方式一:同步代碼塊(處理實現Runnable安全問題,Thread實現類實現的話,需要加static保證當前對象的唯一性)
synchronized(同步監視器){
//需要被同步的代碼
}
說明: 1、操作共享數據的代碼,即爲需要被同步的代碼
2、共享數據:多個線程共同操作的變量。比如:ticket就是共享數據。
3、同步監視器:俗稱鎖。任何一個類的對象,都可以充當鎖。
要求: 多個線程必須要公用同一把鎖
案例(窗口取票案例):
class Windows implements Runnable{
private int tickets = 100;
private Object ob = new Object(); //線程的同一把鎖,即同一個對象
@Override
public void run() {
while (true) {
synchronized(ob) { //通過synchronized來加鎖
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":買票,票號爲:" + tickets);
tickets--;
} else {
break;
}
}
}
}
}
public class Window {
public static void main(String[] args) {
Windows w = new Windows();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
1.2、方式二:同步方法
關於同步方法總結:
1、同步方法仍然涉及到同步監器,只是不需要我門顯示的聲明。
2、非靜態同步方法,同步監視器是this
靜態的同步方法,同步監視器是:當前類本身
當使用Thread類的子類時,需要把同步方法設置爲static public static synchronized void way()
class Windows implements Runnable{
private int tickets = 100;
@Override
public void run() {
while (true) {
way();
}
}
public synchronized void way() { //通過synchronized來加鎖,代表的是this當前的Windows類
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":買票,票號爲:" + tickets);
tickets--;
}
}
}
public class Window {
public static void main(String[] args) {
Windows w = new Windows();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
1.3、Lock()鎖 ————JDK5.0新增
import java.util.concurrent.locks.ReentrantLock;
class Windowt implements Runnable {
private int ticktes = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try{
//加放鎖
lock.lock();
if (ticktes > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "當前的票數爲:" + ticktes);
ticktes--;
} else {
break;
}
}finally {
//釋放鎖
lock.unlock();
}
}
}
}
public class ThreadLock {
public static void main(String[] args) {
Windowt window = new Windowt();
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}