Java线程基本同步方式

Java线程基本同步方式,第1张

Java线程基本同步方式

应用场景:多用户对同一银行账户进行取款

取款线程类,每个用户对应一个线程对象

多个用户共享同一个银行账户,使用Runnable解决

对于具体的实现过程中出现冲突问题时,是由于当一个账户判断银行账户中的数目大于给定值可以取款时,这时将cpu释放出去,去执行另一个线程,另一个线程执行完后,回到该线程继续执行时,实际账户中的数目已经不够但是因为之前已经判断,所以还会接着执行下去,这时就会出错。为了解决这个问题

同步代码
synchronized(同步监视器){
*     必须是引用数据类型,不能是基本数据类型
*     在同步代码块中可以改变同步监视对象的值,但是不能改变其引用
*     //account=new account
*     建议使用final来修饰同步监视器
*    尽量不要使用String和包装类来做同步监视器
*    可以创建一个专门的同步监视器没有任何含义
*    共享资源用来做锁

将一定不能分开的放在synchronized(){}里面

synchronized (account){}

第一个线程来到同步代码块,发现同步监视器是open状态,关闭,然后执行其中的代码

第一个线程执行过程中,发生了线程切换(阻塞  就绪),第一个线程失去cpu,但是没有开锁

第二个线程获取cpu,来到同步代码块,发现同步监视器是close状态,无法执行其中的代码,第二个线程也进入阻塞状态

第一个线程再次获取cpu,来到同步代码块,继续执行后续代码,同步代码执行完毕,释放锁open

第二线程发现同步监视器是open状态,拿到锁并将锁变为close状态,有阻塞态进入就绪态,在进入运行态

优点:安全

缺点:效率低  可能出现死锁 

同步方法

定义的方法上面加synchronized()

  public void run() {
      //取款
        withdraw();

    }

    public synchronized void  withdraw() { //同步方法的锁
        if (account.getBalance() >= 400) { //临界代码
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            account.withDraw(400);
            System.out.println(Thread.currentThread().getName()
                    + "取款成功,当前余额:" + account.getBalance());

        }
        else{
            //余额不足
            System.out.println(Thread.currentThread().getName()
                    + "取款失败,当前余额:" + account.getBalance());
        }
    }

    public synchronized static void method1() {
        //静态的同步方法的锁是类名.class 类对象AccountRunnable
        Class clazz=AccountRunnable.class;
    }

    public synchronized static void method2() {

    }

 注意:

*非静态同步方法的锁:this

* 静态同步方法的锁:类名.class

*3.同步方法和同步代码块谁的效率高 : 同步代码块效率高

Lock锁

注意:如果同步代码有异常,要将unlock()写入finally语句块

Reentrantlock  可重入锁  会做一个计数

首先需要创建锁

private Lock lock = new ReentrantLock();
try {
            if (account.getBalance() >= 400) { //临界代码
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                account.withDraw(400);
                System.out.println(Thread.currentThread().getName()
                        + "取款成功,当前余额:" + account.getBalance());

            }
            else{
                //余额不足
                System.out.println(Thread.currentThread().getName()
                        + "取款失败,当前余额:" + account.getBalance());
            }
        } finally {
            //解锁
            lock.unlock();
        }
线程同步练习:4个窗口卖100张票

使用同步代码块,不能够将while都放在同步代码块中,这样会使得一个线程全部执行完

锁的只能是执行一次

package synch4;

public class TicketRunnalble1 implements Runnable{
    private int ticketnum = 100;


    @Override
    public void run() {


        while (true) {
            synchronized (this) {
                if (ticketnum <= 0) {
                    break;
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖出了第"
                        + (100 - ticketnum+1) + "张票");
                ticketnum--;

            }

        }

    }

    public static void main(String[] args) {
        Runnable runnable = new TicketRunnalble1();
        //创建4个线程模拟4个窗口
        Thread thread1 = new Thread(runnable);
        Thread thread2= new Thread(runnable);
        Thread thread3 = new Thread(runnable);
        Thread thread4 = new Thread(runnable);
        thread1.setName("thread1");
        thread2.setName("thread2");
        thread3.setName("thread3");
        thread4.setName("thread4");

        //窗口开始买票(启动线程)
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }


}
同步方法
public class TicketRunnalble2 implements Runnable{
    private int ticketnum = 100;


    @Override
    public void run() {


        while (ticketnum>0) {
            sellOne();
        }


    }

    public synchronized void sellOne() {
        if (ticketnum <= 0) {
            return;
        }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

        System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketnum+1) + "张票");
        ticketnum--;


    }
lock锁
 private int ticketnum = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {


        while (true) {
            //上锁
            lock.lock();
            try{
                if (ticketnum <= 0) {
                    break;
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketnum + 1) + "张票");
                ticketnum--;

            }finally {
                lock.unlock();
            }

        }

    }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5582784.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存