synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可package 多线程.syn;
/**
* @author 缘友一世
* date 2022/11/11-22:46
*/
//不安全的买票 同一个票被多个人买去
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"a").start();
new Thread(buyTicket,"b").start();
new Thread(buyTicket,"c").start();
}
}
class BuyTicket implements Runnable {
//票
private int ticketNums=10;
boolean flag=true;
@Override //买票
public void run() {
while(flag) {
try {
buy();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void buy() throws InterruptedException {
//判断是否还有票
if(ticketNums<=0) {
flag=false;
return;
}
//模拟延时
Thread.sleep(1000);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
}

package 多线程.syn;
/**
* @author 缘友一世
* date 2022/11/11-22:59
*/
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account(100, "学费");
Drawing a1 = new Drawing(account, 50, "a");
Drawing b1 = new Drawing(account, 60, "b");
a1.start();
b1.start();
}
}
//账户
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
class Drawing extends Thread {
Account account;
int drawingMoney;
int nowMoney;
public Drawing(Account account, int drawingMoney, String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
//判断有没有钱
if(account.money-drawingMoney<0) {
System.out.println(Thread.currentThread().getName()+"钱不够了,取不了了");
return ;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//计算账户的余额
account.money=account.money-drawingMoney;
//本人的手中的钱
nowMoney=nowMoney+drawingMoney;
System.out.println(account.name+"余额"+account.money);
System.out.println(this.getName()+"手里的钱"+nowMoney);
}
}

/**
* @author 缘友一世
* date 2022/11/11-23:22
*/
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<10000;i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}

publicsynchronizedvoidmethod(intargs){}
synchronized(obj){}package 多线程.syn;
/**
* @author 缘友一世
* date 2022/11/11-22:46
*/
//不安全的买票
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
Thread a = new Thread(buyTicket, "a");
Thread b = new Thread(buyTicket, "b");
Thread c = new Thread(buyTicket, "c");
a.start();
b.start();
c.start();
}
}
class BuyTicket implements Runnable {
//票
private int ticketNums=200;
boolean flag=true;
@Override //买票
public void run() {
while(flag) {
buy();
}
}
//synchronized 同步方法,锁的是this即 BuyTicket对象
private synchronized void buy() {
//判断是否还有票
if(ticketNums<=0) {
flag=false;
return;
}
//模拟延时
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
}


/**
* @author 缘友一世
* date 2022/11/11-22:59
*/
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account(100, "学费");
Drawing a1 = new Drawing(account, 50, "a");
Drawing b1 = new Drawing(account, 60, "b");
a1.start();
b1.start();
}
}
// 账户
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
class Drawing extends Thread {
Account account;
int drawingMoney;
int nowMoney;
public Drawing(Account account, int drawingMoney, String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
// 默认情况下锁的时this
// 这个案例我们不需要锁对象,而是需要锁定账户中的钱数
@Override
public void run() {
synchronized (account) {
// 判断有没有钱
if (account.money - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "钱不够了,取不了了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 计算账户的余额
account.money = account.money - drawingMoney;
// 本人的手中的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name + "余额" + account.money);
System.out.println(this.getName() + "手里的钱" + nowMoney);
}
}
}

package 多线程.syn;
import java.util.ArrayList;
/**
* @author 缘友一世
* date 2022/11/11-23:22
*/
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<1000;i++) {
new Thread(()->{
synchronized (list) {
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}

package 多线程.Day03;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author 缘友一世
* date 2022/11/12-10:22
*/
public class TestJUC {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
for(int i=1;i<=1000;i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(100);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}

/**
* @author 缘友一世
* date 2022/11/12-10:31
*/
public class DeadLock {
public static void main(String[] args) {
new Makeup(1,"纣王").start();
new Makeup(0,"秦始皇").start();
}
}
class Country {
}
class Beauty{
}
class Makeup extends Thread {
//需要的资源只有一份,用static来保证只有一份
static Country country=new Country();
static Beauty beauty=new Beauty();
int choice;//选择
String Name;//拥有江山的人
public Makeup(int choice, String name) {
this.choice = choice;
Name = name;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//要获得就要先加锁
//两者相互僵持
private void makeup() throws InterruptedException {
if(choice==0) {
synchronized (country) {
System.out.println(this.Name+"获得江山");
Thread.sleep(1000);
synchronized (beauty) {
System.out.println(this.Name+"获得美人");
}
}
}else {
synchronized (beauty) {
System.out.println(this.Name+"获得美人");
synchronized (country) {
System.out.println(this.Name+"获得江山");
}
}
}
}
}
程序相互僵持,一直无法结束

避免死锁
private void makeup() throws InterruptedException {
if(choice==0) {
synchronized (country) {
System.out.println(this.Name+"获得江山");
Thread.sleep(1000);
}
synchronized (beauty) {
System.out.println(this.Name+"获得美人");
}
}else {
synchronized (beauty) {
System.out.println(this.Name+"获得美人");
}
synchronized (country) {
System.out.println(this.Name+"获得江山");
}
}
}

从JDK5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。
同步锁使用Lock对象充当java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。
锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象
ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存请义,在实现线程安全的控制中,比较常用的ReentrantLock,可以显式加锁、释放锁。
模板
class x {
private final ReentrantLock lock = new ReentrantLock();
public void m() {
lock.lock;
try{
//保证线程安全的代码
}finally {
lock.unlock;
//如果同步代码有异常,要将unlock写入Finally语句块
}
}
}
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 缘友一世
* date 2022/11/12-11:52
*/
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
new Thread(testLock2).start();
new Thread(testLock2).start();
new Thread(testLock2).start();
}
}
class TestLock2 implements Runnable {
private final ReentrantLock lock = new ReentrantLock();
int ticketNums = 10;
@Override
public void run() {
while (true) {
try {
lock.lock();//显示加锁
if (ticketNums > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(ticketNums--);
} else {
break;
}
} finally {
lock.unlock();//解锁
}
}
}
}

| Lock | synchronized |
|---|---|
| Lock是显式锁 ,需要手动的开启和释放 | synchronized是隐式锁,出了作用域就自动释放 |
| Lock只有代码块锁 | synchronized有代码块锁和方法锁 |
| 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且就有良好的拓展性 |
- Lock>同步代码块(已经进入了方法体分配了相应资源)>同步方法(在方法体之外)