java中任何對象預設都會有一個互斥鎖标記,用來配置設定給線程。也可以選擇這個所标記 沒有配置設定給任何線程/或者隻能給一個線程。 隻有拿到對象所标記的線程才能進入到對該對象加鎖的同步代碼塊。 同步鎖的是對象 線程退出同步代碼塊(線程執行完畢 确切來說,run方法執行完畢),會釋放相應的鎖标記。
java中任何對象預設都會有一個互斥鎖标記,用來配置設定給線程。也可以選擇這個所标記 沒有配置設定給任何線程/或者隻能給一個線程。 隻有拿到對象所标記的線程才能進入到對該對象加鎖的同步代碼塊。 同步鎖的是對象 線程退出同步代碼塊(線程執行完畢 确切來說,run方法執行完畢),會釋放相應的鎖标記。
synchronized 修飾代碼塊 對象鎖标記 上代碼
package com.baigu.demo1.stack;
public class TestStack {
public static void main(String[] args) throws InterruptedException {
Stack stack = new Stack();
// stack.print();
// stack.posh('C');
// stack.print();
// stack.pop();
// stack.print();
PushThread t1 = new PushThread(stack);
PopThread t2 = new PopThread(stack);
stack.print();
System.out.println();
t1.start();
t2.start();
Thread.sleep(1000); //睡一秒讓t1 t2線程執行結束在執行主線程
stack.print();
}
}
class Stack{
private char[] data={'A','B',' ',' ',' ',' ',' ',' '};
private int index=2; //記錄數組中有效元素的個數
public void posh(char c){
System.out.println(c+" poshed! 入棧");
data[index]=c;
try {
Thread.sleep(1000); //睡0.1秒類似于時間片到期
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
}
public void pop(){
index --;
System.out.println(data[index]+" poped! 出棧");
data[index]=' ';
}
public void print(){
for (char s:data)
System.out.print(s);
}
}
class PushThread extends Thread{
Stack s;
public PushThread(Stack s) {
this.s = s;
}
@Override
public void run() {
// s.posh('C');
synchronized (s){ //同步代碼塊 參數為對象的引用 對象鎖标記
s.posh('C');
}
}
}
class PopThread extends Thread{
Stack s;
public PopThread(Stack s) {
this.s = s;
}
@Override
public void run() {
synchronized (s){ //同步代碼塊 參數為對象的引用 對象鎖标記
s.pop();
}
}
}
synchronized 修飾方法 方法鎖标記 上代碼
package com.baigu.demo1.stack;
public class Testsynchronizedmethod {
public static void main(String[] args) throws InterruptedException {
StackTwo stack = new StackTwo();
PushThreadTwo t1 = new PushThreadTwo(stack);
PopThreadTwo t2 = new PopThreadTwo(stack);
stack.print();
System.out.println();
t1.start();
t2.start();
Thread.sleep(1000); //睡一秒讓t1 t2線程執行結束在執行主線程
stack.print();
}
}
class StackTwo{
private char[] data={'A','B',' ',' ',' ',' ',' ',' '};
private int index=2; //記錄數組中有效元素的個數
public synchronized void posh(char c){ //方法鎖标記
System.out.println(c+" poshed! 入棧");
data[index]=c;
try {
Thread.sleep(800); //睡0.1秒類似于時間片到期
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
}
public synchronized void pop(){ //方法鎖标記
index --;
System.out.println(data[index]+" poped! 出棧");
data[index]=' ';
}
public void print(){
for (char s:data)
System.out.print(s);
}
}
class PushThreadTwo extends Thread{
StackTwo s;
public PushThreadTwo(StackTwo s) {
this.s = s;
}
@Override
public void run() {
s.posh('C');
}
}
class PopThreadTwo extends Thread{
StackTwo s;
public PopThreadTwo(StackTwo s) {
this.s = s;
}
@Override
public void run() {
s.pop();
}
}
synchronized鎖機制 無論是同步代碼塊還是作為修飾符 兩種本質相同
下面是做的一些總結
線程同步:
當多線程并發通路臨界資源(同一個對象)時,多線程同時通路同一個對象時,如果破壞了
原子操作(不可分割的操作),就會造成資料不一緻。和資料庫中的事務類似。
1.synchronized(o){}: 對對象o加鎖的同步代碼塊 同步代碼塊保護原子操作不被破壞。
個人了解:主線程運作優于自己建立的線程運作。
java中任何對象預設都會有一個互斥鎖标記,用來配置設定給線程。也可以選擇這個所标記
沒有配置設定給任何線程/或者隻能給一個線程。
隻有拿到對象所标記的線程才能進入到對該對象加鎖的同步代碼塊。
同步鎖的是對象
線程退出同步代碼塊(線程執行完畢 真正意義上,run方法結束),會釋放相應的鎖标記。
2.synchronized(用作方法修飾符),synchronized修飾的方法叫做同步方法
同步方法指的是在整個方法的範圍内對目前對象加鎖。
隻有拿到對象所标記的線程才能調用該對象的同步方法。
同步方法等同于同步代碼塊。
鎖池:任何對象都有的一個空間,用來存放等待該對象鎖标記的線程 (一個或多個)
利用鎖機制解決線程的同步問題,隻有拿到對象所标記的線程才能進入到對該對象加鎖的
同步代碼塊(原子操作)。
線程架構圖
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxI1MihGeyIWMkdVYoJ1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQTN0IDN0ETM5IzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
糾正一點,較之前說的五中狀态,現在又增加了一種 鎖池狀态。
這輩子堅持與不堅持都不可怕,怕的是獨自走在堅持的道路上。 歡迎加入技術群聊。
這輩子堅持與不堅持都不可怕,怕的是獨自走在堅持的道路上。 歡迎加入技術群聊。