首页 > 其他分享 >线程同步3

线程同步3

时间:2023-01-06 17:55:05浏览次数:28  
标签:同步 name Thread System 线程 println new public

线程同步

并发 同一对象被多个线程同时操作

线程同步:

处理多线程问题时,多线程访问同一个对象,并且某些线程还想修改这个对象,这时候我们就需要线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕1,下一个线程在使用

三大安全案例

//不安全取钱
package test1;
//不安全取钱
public class Demo2 {
    public static void main(String[] args) {
        Account sang = new Account("sang", 1000);
        Bank bank = new Bank(sang,500,"me");
        Bank bank1 = new Bank(sang,900,"other");
        bank.start();
        bank1.start();


    }
}
//账户
class Account {
    private String name;//账户名
    private int money;//账户余额
    public Account() {
    }
    public Account(String name, int money) {
        this.name = name;
        this.money = money;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setMoney(int money){
        this.money = money;
}
    public int getMoney() {
        return money;
    }
}

//银行模拟取款
class Bank extends Thread{
    Account account;//
    private int gotoOut;

    public Bank() {
    }
    public Bank(Account account, int gotoOut,String name) {
        super(name);
        this.account = account;
        this.gotoOut = gotoOut;
    }
    @Override
    public void run() {
        int remainder = account.getMoney() - this.gotoOut;
        if (this.gotoOut>account.getMoney()){
            System.out.println(Thread.currentThread().getName() + "钱不够,请重新输入取款金额!");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            account.setMoney(remainder);
            System.out.println(account.getName() + "Bank金额剩余:" + account.getMoney());
            System.out.println(Thread.currentThread().getName() + "取款" + account.getMoney());



    }

    public int getGotoOut() {
        return gotoOut;
    }

    public void setGotoOut(int gotoOut) {
        this.gotoOut = gotoOut;
    }
}
package test1;
//不安全买票,线程不安全有负数
public class Demo1 {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();
        new Thread(buyTicket,"我").start();
        new Thread(buyTicket,"黄牛党").start();
        new Thread(buyTicket,"别人").start();
    }
}
class BuyTicket implements Runnable{
    private int TicketNum = 20;//票数
    boolean flag = true;
    @Override
    public void run() {
        while (flag){//外部停止方式
            try {
                Thread.sleep(100);
                buy();
                if (TicketNum <= 1){
                    flag = false;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void buy(){
        System.out.println(Thread.currentThread().getName()
        + "买了"+ this.TicketNum--);
    }
}
package test1;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{list.add(Thread.currentThread().getName());}).start();
        }
        Thread.sleep(1000);
        System.out.println(list.size());//7219
    }
}

同步方法

同步块

package test1;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list) {
                    list.add(Thread.currentThread().getName());
                }}).start();
        }
        Thread.sleep(1000);
        System.out.println(list.size());//7219
    }
}

//synchronized默认锁定是this.
    @Override
    public void run() {
        //锁的对象就是变化的量,需要增删改的对象
        synchronized (account){
            int remainder = account.getMoney() - this.gotoOut;
            //判断钱够不够
            if (this.gotoOut>account.getMoney()){
                System.out.println(Thread.currentThread().getName() + "钱不够,请重新输入取款金额!");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.setMoney(remainder);
            System.out.println(account.getName() + "Bank金额剩余:" + account.getMoney());
            System.out.println(Thread.currentThread().getName() + "取款" + account.getMoney());
        }
    }
 //synchronized同步关键字,锁的是this,对象
    private synchronized void buy(){
        System.out.println(Thread.currentThread().getName()
        + "买了"+ this.TicketNum--);
    }

疑问,juc安全类型的集合

package test1;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
//线程安全的集合类
public class TestJUC {
    public static void main(String[] args) throws InterruptedException {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }//有点疑惑,如果不加sleep类,还是不到10000,添加sleep后
        Thread.sleep(1000);//不到1000毫秒也不会到10000
        System.out.println(list.size());
    }
}

死锁

package test1;
//多线程互相需要对方锁内的资源,形成僵持,成为死锁
public class DeadLock {
    public static void main(String[] args) {
new MakeEat(0,"sang").start();
new MakeEat(1,"zhang").start();
    }
}
//曲奇饼
class Cookie{

}
//饼干,烤饼
class Biscuit{

}
class MakeEat extends Thread{
    int choose;
    String name;
    static Cookie cookie = new Cookie();//静态变量,只有一个,如果不是静态
    static Biscuit biscuit = new Biscuit();//这不会出现死锁现象
    @Override
    public void run() {
        //吃饼干
        try {
            eat();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    MakeEat(int choose,String name){
        this.choose = choose;
        this.name = name;
    }
    private void eat() throws InterruptedException {
        if (choose == 0){//先吃曲奇饼在吃饼干
            synchronized (cookie){
                System.out.println("吃曲奇饼" + this.name);
                Thread.sleep(3000);//多一会,保证出现死锁
                synchronized (biscuit){
                    System.out.println("吃饼干" + this.name);
                    Thread.sleep(1000);
                }
            }
//解决只需将synchronized放出来一个即可
        }else {
            synchronized (biscuit){
                System.out.println("吃饼干" + this.name);
                Thread.sleep(1000);
                synchronized (cookie){
                    System.out.println("吃曲奇饼" + this.name);
                    Thread.sleep(1000);
                }
            }

        }
    }
}

解决

 private void eat() throws InterruptedException {
        if (choose == 0){//先吃曲奇饼在吃饼干
            synchronized (cookie){
                System.out.println("吃曲奇饼" + this.name);
                Thread.sleep(3000);//多一会,保证出现死锁
            }
            synchronized (biscuit){
                System.out.println("吃饼干" + this.name);
                Thread.sleep(1000);
            }
//解决只需将synchronized放出来一个即可
        }else {
            synchronized (biscuit){
                System.out.println("吃饼干" + this.name);
                Thread.sleep(1000);
            }
            synchronized (cookie){
                System.out.println("吃曲奇饼" + this.name);
                Thread.sleep(1000);
            }
        }

死锁避免方法

Lock(锁)

ReentrantLock类实现了Lock,它拥有了与synchronized相同的并发性和内存语义,再实现线程安全控制中,比较常用的是ReentrantLock,可以显示加锁、释放锁。

package test1;

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
    public static void main(String[] args) {
        TestLock1 testLock1 = new TestLock1();
        new Thread(testLock1).start();
        new Thread(testLock1).start();
        new Thread(testLock1).start();
    }
}
class TestLock1 implements Runnable{
    private int testNum = 20;
    private final ReentrantLock reentrantLock = new ReentrantLock();
    @Override
    public void run() {
        reentrantLock.lock();
        try {
            while(this.testNum > 0){
                Thread.sleep(100);
                System.out.println(this.testNum--);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            reentrantLock.unlock();
        }
    }
}

synchronized与Lock的对比

标签:同步,name,Thread,System,线程,println,new,public
From: https://www.cnblogs.com/1234sdg/p/17031225.html

相关文章

  • java多线程创建一个简单的案例
    1、创建一个简单的线程,不需要去创建个RunnableThreadthread=newThread(newRunnable(){@Overridepublicvoidrun(){//todo你要执行的方法}......
  • 【Java】线程池梳理
    【Java】线程池梳理前言线程池:本质上是一种对象池,用于管理线程资源。在任务执行前,需要从线程池中拿出线程来执行。在任务执行完成之后,需要把线程放回线程池。通过线程的......
  • 1_认识同步和异步
    什么是同步交互首先用户向HTTP服务器提交一个处理请求。接着服务器端接收到请求后,按照预先编写好的程序中的业务逻辑进行处理,比如和数据库服务器进行数据信息交换。最后,服......
  • 1_认识同步和异步
    什么是同步交互首先用户向HTTP服务器提交一个处理请求。接着服务器端接收到请求后,按照预先编写好的程序中的业务逻辑进行处理,比如和数据库服务器进行数据信息交换。最后,服......
  • 多线程
    一、多线程概述1.1进程和线程概述进程:操作系统中的应用程序,一个进程就是一个应用程序。进程A和进程B的内存独立不共享资源。线程:CPU调度的最小单元,进程的一个执行流/......
  • Beyond Compare 4 for Mac(文件同步对比工具)v4.4.4(27058)中文版
    BeyondCompare4mac版哪里有?BeyondCompare是一款超好用的专业级文件夹及文件同步对比工具!可以帮助你找到并协调源代码、文件夹、图像和数据间的差异,即使包括zip文档中或......
  • 线程状态2
    线程状态2五大状态停止线程线程方法线程停止packagethread;//测试stop/*建议线程正常停止————利用次数不建议是循环*建议使用标志位,设置一个标志位*......
  • 时间同步概览
    Basler接口:千兆网(GigEVision)或CameraLink接口支持PoE的千兆网(GigE)、支持PoCL的CameraLink、USB3.0相机符合GigEVision、USB3Vision和CameraLink标准协议,具......
  • android基础02 - 多媒体、多线程与异步任务、Service、网络
    多媒体通知通知渠道:程序对自己发出的通知进行分类,用户可根据渠道对消息进行屏蔽或设置响铃振动。一个应用的通知渠道一旦创建就无法再修改,只能再创建新的可在Activity、......
  • java中的多线程
    一.线程的创建线程的创建方式有两种:一种是继承Thread类,重写run()方法【这里的run()方法只是普通的方法】,在主方法中,创建该类的对象,调用对象的start()方法。二种是实现R......