26day
线程同步方法(synchronized)
//同步方法
public synchronized void method(int args){}
//会影响效率
package com.wang.syn;
//不安全的取钱
public class UnSafeBank {
public static void main(String[] args) {
Account account = new Account(1000,"wangyan");
Drawing you = new Drawing(account,50,"夏雨");
Drawing she = new Drawing(account,100,"夏风");
you.start();
she.start();
}
}
//账户
class Account{
int money = 0;
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;
}
//取钱
//synchronized默认锁的是this
public void run() {
//锁的对象就是变化的量,需要增删改的对象
synchronized (account){
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"账户余额不足");
return;
}
//sleep放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额 = 余额 - 你取得钱数
account.money = account.money - drawingMoney;
//你手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name+"余额为"+account.money);
System.out.println(this.getName()+"取到了"+nowMoney);
}
}
}
package com.wang.syn;
//不安全的买票
public class UnSafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"夏雨").start();
new Thread(station,"夏风").start();
new Thread(station,"夏明").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10;
private boolean flag = true;//外部停止方式标志位
public void run() {
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//synchronized 同步方法 锁的是this
private synchronized void buy() throws InterruptedException {
//判断是否有票
if (ticketNums <= 0){
flag = false;
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--+"张票");
}
}
package com.wang.syn;
import java.util.ArrayList;
//线程不安全的集合
public class UnSafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
测试JUC安全类型的集合(CopyOnWriteArrayList)
package com.wang.syn;
import java.util.concurrent.CopyOnWriteArrayList;
//测试JUC安全类型的集合
public class TestJUC {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
死锁
-
多个线程各自占有一些资源,并且互相等待其他线程占有的资源才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的情况,某一块同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题
-
产生死锁的四个必要条件:
-
互斥条件:一个资源每次只能被一个进程使用
-
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
-
不剥削条件:进程已获得的资源,在未使用完之前,不能强行剥削
-
循环等待条件:若干个进程之间形成的一种头尾相接的循环等待资源关系
-
package com.wang.thread;
//死锁:多个线程互相持有对方的资源,形成僵持
public class DeadLock {
public static void main(String[] args) {
Makeup girl1 = new Makeup(0,"夏雨");
Makeup girl2 = new Makeup(0,"夏风");
new Thread(girl1).start();
new Thread(girl2).start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
//化妆
class Makeup extends Thread{
//需要的资源只有一份,用static来保证只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//使用化妆品的人
Makeup(int choice,String girlName){
this.choice = choice;
this.girlName = girlName;
}
public void run() {
//化妆
try {
makeup();
} catch (Exception e) {
e.printStackTrace();
}
}
//化妆,互相持有对方的锁,需要拿到对方的资源
private void makeup() throws Exception {
if (choice==0){
synchronized (lipstick){//获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(1000);
}
synchronized (mirror) {//获得镜子的嗦
System.out.println(this.girlName+"获得镜子的锁");
}
}else {
synchronized (mirror){//获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
Thread.sleep(2000);
}
synchronized (lipstick) {//获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
synchronized和lock的对比
-
lock是显示锁(手动开启手动结束)synchronized是隐式锁,出了作用域自动释放
-
lock只有代码块锁,synchronized有代码块锁和方法锁
-
使用lock锁,jvm将花费嘉绍的时间来调度线程,性能更好,并且具有更好的扩展性
-
优先使用顺序:
lock>同步代码块(已经进入了方法体,分配了相应的资源)>同步方法
ReentrantLock可重入锁
# day26
## 线程同步方法(synchronized)
```java//同步方法public synchronized void method(int args){}//会影响效率```
```javapackage com.wang.syn;
//不安全的取钱public class UnSafeBank { public static void main(String[] args) { Account account = new Account(1000,"wangyan"); Drawing you = new Drawing(account,50,"夏雨"); Drawing she = new Drawing(account,100,"夏风");
you.start(); she.start(); }}
//账户class Account{ int money = 0; 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;
}
//取钱 //synchronized默认锁的是this @Override public void run() { //锁的对象就是变化的量,需要增删改的对象 synchronized (account){ //判断有没有钱 if (account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"账户余额不足"); return; } //sleep放大问题的发生性 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
//卡内余额 = 余额 - 你取得钱数 account.money = account.money - drawingMoney; //你手里的钱 nowMoney = nowMoney + drawingMoney;
System.out.println(account.name+"余额为"+account.money); System.out.println(this.getName()+"取到了"+nowMoney); } }
}```
```javapackage com.wang.syn;
//不安全的买票public class UnSafeBuyTicket { public static void main(String[] args) { BuyTicket station = new BuyTicket(); new Thread(station,"夏雨").start(); new Thread(station,"夏风").start(); new Thread(station,"夏明").start(); }}class BuyTicket implements Runnable{
private int ticketNums = 10; private boolean flag = true;//外部停止方式标志位
@Override public void run() { while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } //synchronized 同步方法 锁的是this private synchronized void buy() throws InterruptedException { //判断是否有票 if (ticketNums <= 0){ flag = false; return; } //模拟延时 Thread.sleep(100); //买票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--+"张票");
}}```
```javapackage com.wang.syn;
import java.util.ArrayList;
//线程不安全的集合public class UnSafeList { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); }
}).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); }}```
测试JUC安全类型的集合(CopyOnWriteArrayList)
```javapackage com.wang.syn;
import java.util.concurrent.CopyOnWriteArrayList;
//测试JUC安全类型的集合public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); }}```
## 死锁
- 多个线程各自占有一些资源,并且互相等待其他线程占有的资源才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的情况,某一块同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题
- 产生死锁的四个必要条件: 1. 互斥条件:一个资源每次只能被一个进程使用 2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放 3. 不剥削条件:进程已获得的资源,在未使用完之前,不能强行剥削 4. 循环等待条件:若干个进程之间形成的一种头尾相接的循环等待资源关系
```javapackage com.wang.thread;
//死锁:多个线程互相持有对方的资源,形成僵持public class DeadLock { public static void main(String[] args) {
Makeup girl1 = new Makeup(0,"夏雨"); Makeup girl2 = new Makeup(0,"夏风");
new Thread(girl1).start(); new Thread(girl2).start(); }}//口红class Lipstick{
}//镜子class Mirror{
}//化妆class Makeup extends Thread{
//需要的资源只有一份,用static来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror();
int choice;//选择 String girlName;//使用化妆品的人
Makeup(int choice,String girlName){ this.choice = choice; this.girlName = girlName; }
@Override public void run() { //化妆 try { makeup(); } catch (Exception e) { e.printStackTrace(); } }
//化妆,互相持有对方的锁,需要拿到对方的资源 private void makeup() throws Exception { if (choice==0){ synchronized (lipstick){//获得口红的锁 System.out.println(this.girlName+"获得口红的锁"); Thread.sleep(1000); } synchronized (mirror) {//获得镜子的嗦 System.out.println(this.girlName+"获得镜子的锁"); } }else { synchronized (mirror){//获得镜子的锁 System.out.println(this.girlName+"获得镜子的锁"); Thread.sleep(2000); } synchronized (lipstick) {//获得口红的锁 System.out.println(this.girlName+"获得口红的锁"); } } }}```
## Lock(锁)
synchronized和lock的对比
- lock是显示锁(手动开启手动结束)synchronized是隐式锁,出了作用域自动释放
- lock只有代码块锁,synchronized有代码块锁和方法锁
- 使用lock锁,jvm将花费嘉绍的时间来调度线程,性能更好,并且具有更好的扩展性
- 优先使用顺序:
lock>同步代码块(已经进入了方法体,分配了相应的资源)>同步方法
***ReentrantLock可重入锁***

浙公网安备 33010602011771号