前言
?????synchronized是同步的意思骨稿,是java提供的一個(gè)關(guān)鍵字,用于多線程訪問共享資源時(shí)姜钳,保證線程訪問安全的一種手段坦冠。同時(shí)synchronized是一種可重入鎖,但是是非公平鎖哥桥。
一蓝牲、對(duì)象鎖
用法一 同步代碼塊
?????java 萬物皆對(duì)象,多線程的情況下泰讽,鎖對(duì)象必須是同一個(gè)例衍,也就是多個(gè)線程共享一把鎖資源。
synchronized(鎖對(duì)象){
//同步代碼塊
}
案例
?????synchronized關(guān)鍵字結(jié)合notity()方法和wait()方法實(shí)現(xiàn)多線程交替打印已卸。
package hchang.demo.Lock;
/**
* synchronized 配合wait()和notify()方法實(shí)現(xiàn)兩個(gè)線程的交替打印
* sycnronized 用法:對(duì)象鎖(同步代碼塊)
* 鎖對(duì)象在語法上可以是任意一個(gè)對(duì)象佛玄,但是對(duì)象必須是同一個(gè),也就是多線程之間公用一把鎖
*/
public class SynchronizedDemo {
static String str1= "ABCDEFG";
static String str2 = "123456";
public static void main(String[] args){
Object ot = new Object();
char[] char1 = str1.toCharArray();
char[] char2 = str2.toCharArray();
Thread td1 = new Thread(new Runnable() {//匿名內(nèi)部類
@Override
public void run() {
synchronized (ot) {
//同步代碼塊 ot是鎖對(duì)象
for (char c:char1) {
System.out.println(c);
ot.notify();
try {
ot.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ot.notify();//誰先完成叫醒對(duì)方累澡,否則永遠(yuǎn)有一個(gè)線程在wait,程序無法結(jié)束
}
}
},"ThreadA");
Thread td2 = new Thread(new Runnable() {
@Override
public void run() {
//同步代碼塊 ot是鎖對(duì)象
synchronized (ot) {
for (char c:char2) {
System.out.println(c);
ot.notify();
try {
ot.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ot.notify();//誰先完成叫醒對(duì)方梦抢,否則永遠(yuǎn)有一個(gè)線程在wait,程序無法結(jié)束
}
}
},"ThreadB");
td1.start();
td2.start();
}
}
用法二 同步方法
?????synchronized關(guān)鍵字修飾非靜態(tài)方法,鎖的對(duì)象是this愧哟,就是當(dāng)前非靜態(tài)方法所在的類的對(duì)象奥吩。
修飾符 synchronized 返回值類型 方法名(形參列表){
//同步方法體
}
案例
?????一個(gè)線程使用同步代碼塊哼蛆,一個(gè)線程使用同步方法,實(shí)現(xiàn)用戶同步訂購商品霞赫。
package hchang.demo.Lock;
/**
* synchronized 用法:對(duì)象鎖
*
*/
public class SynchronizedClassDemo {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB(threadA);
threadB.start();
threadA.start();
}
}
class ThreadB extends Thread{
private Object lock;
public ThreadB(Object lock) {
this.lock = lock;
}
@Override
public void run() {
Bshopping();
}
public void Bshopping() {
synchronized (lock) {
System.out.println("用戶B瀏覽商品");
System.out.println("用戶B加入購物車");
System.out.println("用戶B提交訂單");
System.out.println("用戶B支付");
}
}
}
class ThreadA extends Thread{
@Override
public void run() {
Ashopping();
}
/**
* synchronized 加在實(shí)例方法上腮介,代表鎖對(duì)象是this
*/
public synchronized void Ashopping() {
System.out.println("用戶A瀏覽商品");
System.out.println("用戶A加入購物車");
System.out.println("用戶A提交訂單");
System.out.println("用戶A支付");
}
}
二、類鎖
?????synchronized關(guān)鍵字修飾靜態(tài)方法端衰,鎖的對(duì)象是類對(duì)象叠洗,就是當(dāng)前靜態(tài)方法所在的類的字節(jié)碼對(duì)象。
修飾符 synchronized static 返回值類型 方法名(形參列表){
//同步方法體
}
案例
?????一個(gè)線程使用同步代碼塊旅东,一個(gè)線程使用靜態(tài)同步方法灭抑,實(shí)現(xiàn)用戶同步訂購商品。
package hchang.demo.Lock;
/**
* synchronized 用法:類鎖
* 1抵代、類鎖只有一把鎖 對(duì)象鎖可以有多個(gè)
* 2腾节、class 對(duì)象只有一個(gè)
*/
public class SynchronizedClassDemo {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB(threadA.getClass());
threadB.start();
threadA.start();
}
}
class ThreadB extends Thread{
private Object lockClass;
public ThreadB(Object lockClass) {
this.lockClass = lockClass;
}
@Override
public void run() {
Bshopping();
}
public void Bshopping() {
synchronized (lockClass) {
System.out.println("用戶B瀏覽商品");
System.out.println("用戶B加入購物車");
System.out.println("用戶B提交訂單");
System.out.println("用戶B支付");
}
}
}
class ThreadA extends Thread{
@Override
public void run() {
Ashopping();
}
/**
* synchronized 加在靜態(tài)方法上武通,代表鎖對(duì)象是當(dāng)前對(duì)象的字節(jié)碼對(duì)象眼五,也就是類對(duì)象
*/
public synchronized static void Ashopping() {
System.out.println("用戶A瀏覽商品");
System.out.println("用戶A加入購物車");
System.out.println("用戶A提交訂單");
System.out.println("用戶A支付");
}
}