java线程同步问题例题

java线程同步问题例题,第1张

定义:

  1. 在多线程编程,一些敏感的数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多只有一个线程访问,以保护数据的完整性。
  2. 线程同步,就是当有一个线程对内存进行 *** 作时,其他线程都不可以对这个内存地址进行 *** 作,直到该线程完成 *** 作,其他线程才能对该内存地址进行 *** 作。

同步具体方法-Synchronized:

  1. 同步代码块
    synchronized(对象){//得到对象的锁,才能 *** 作同步代码块
        //需被同步的代码
    }
  2. synchronized还可以放在方法声明中,表示整个方法-为同步方法
    public synchronized void m(String name){
        //需被同步的代码
    }

作业1要求:

  1. 在main方法中启动两个线程
  2. 第一个线程循环随机打印100以内的整数
  3. 第二个进程从键盘读取了”Q“命令
package com.yuanhuajun.Homework;

import java.util.Scanner;

/**
 * @author Yhj
 * @date 2022/4/29 8:44
 * @project chapter17
 */


public class Homework01 {
    public static void main(String[] args) {
        T1 t1 = new T1();
        //这是将t1对象传到t2中,用以在t2进程中控制t1;如果用类变量来控制,不需要这样。
        T2 t2 = new T2(t1);
        Thread thread = new Thread(t2);
        //启动两个进程
        t1.start();
        thread.start();
    }
}


class T1 extends Thread {
    static Boolean flag = true;

    public static Boolean getFlag() {
        return flag;
    }

    public static void setFlag(Boolean flag) {
        T1.flag = flag;
    }

    @Override
    public void run() {
        while (flag) {
            System.out.println("T1线程随机打印:" + (int) (Math.random() * 100+ 1));
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果是通过守护进程来控制,这一句无法输出,因为T2结束后,T1直接无条件结束,不会再给时间它输出这一句
        //但是如果是通过控制flag,会输出
        System.out.println("T1线程退出!");
    }
}

class T2 implements Runnable {
    private T1 t1;
    //守护进程
    public T2(T1 t1) {
        this.t1 = t1;
        //方法一,设置守护进程,当目前进程(t2)结束,t1也立刻结束
        t1.setDaemon(true);
    }

    @Override
    public void run() {

        String x;
        do {
            Scanner scanner = new Scanner(System.in);
            x = scanner.next();
        } while (!(x.equals("Q")));
        System.out.println("T2线程退出!");

        //方法二:通过类变量控制
        // T1.setFlag(false);
    }

}

作业2要求:

  1. 有2个用户分别从同一个卡上取钱(总额10000)
  2. 每次都取出1000,余额不足时,就不能取款
  3. 不能出现超取现象
package com.yuanhuajun.Homework;

/**
 * @author Yhj
 * @date 2022/4/29 10:03
 * @project chapter17
 */
public class Homework02 {
    public static void main(String[] args) {
        Withdraw withdraw = new Withdraw();
        Thread thread1 = new Thread(withdraw);
        Thread thread2 = new Thread(withdraw);
        thread1.setName("小米");
        thread2.setName("小牛");
        thread1.start();
        thread2.start();
    }
}

//多个线程共享进程,所以使用实现Runnable方式
class Withdraw implements Runnable {
    //共享10000元
    static int money = 10000;
    static boolean loop = true;

    @Override
    public void run() {
        //通过loop来控制循环
        while (loop) {
            //获取锁
            draw();
        }
    }

    //1.这里使用synchronized 实现线程同步
    //2.多个线程执行到这里,就会去争夺this对象锁
    //3.哪个线程争夺到this对象的锁,就执行业务
    //4.争夺不到的,处于blocked状态,准备继续争夺
    public /*方法一:synchronized */ void draw() {
        //方法二:同步代码块,格式:synchronized(对象){业务}
        //this对象是非公平锁,
        synchronized (this){
            if (money < 1000) {
                System.out.println("钱取完了");
                loop = false;
                return;
            }
            try {
                //休眠,0.1秒
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            money -= 1000;
            //执行完这一句,会短暂的释放锁,继续下一轮锁的争夺
            System.out.println(Thread.currentThread().getName() + "取出1000元,剩余:" + money);
        }

    }
}

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

原文地址: http://outofmemory.cn/langs/788918.html

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

发表评论

登录后才能评论

评论列表(0条)

保存