关于java多线程任务执行时共享资源加锁的方式思考

1.加锁方式:

  1-1.使用synchronized关键字进行方法或代码块的加锁方式

  1-2.使用ReentrantLock类提供的lock()方法的方式

2.代码实现(传统的银行取款存款问题):

  2-1.Account.java类:账户类

package com.java.thread;

import java.util.concurrent.locks.ReentrantLock;
/**
 * 账户类
 * @author steven
 *
 */
public class Account {

    public double money = 6000;
    public ReentrantLock lock = new ReentrantLock();
    public Account(double money){
        this.money = money;
    }
    public void drawmoney(double money,String name){
        synchronized (this) {
            this.money -= money;
            System.out.println(name+"取款后剩余钱数:"+this.money);
        }
    }

    public void drawmoney1(double money,String name){
        lock.lock();
        try {
            this.money -= money;
            System.out.println(name+"取款后剩余钱数:"+this.money);
        }catch (Exception e) {
            // TODO: handle exception
        }finally{
            lock.unlock();
        }
    }

    public synchronized void cunmony(double money,String name){
            this.money += money;
            System.out.println(name+"存款后剩余钱数:"+this.money);
    }

}

  2-2.User.java类:线程实现类

package com.java.thread;

/**
 * 继承线程类,重写run方法
 * @author steven
 *
 */
public class User extends Thread{

    private String username;
    private Account account;
    public User(String username,Account account){
        this.username = username;
        this.account = account;
    }
    public void run(){
        if (username.contains("0")||username.contains("1")||username.contains("2"))
            this.account.cunmony(1000,username);
        else if(username.contains("3"))
            this.account.drawmoney(500, username);
        else
            this.account.drawmoney1(100, username);
    }
    public static void main(String[] args) {
        Account account = new Account(10000);
        User user = null;
        for (int i = 0; i < 5; i++) {
            user = new User("user"+i, account);
            user.setPriority(i+1);
            user.start();
        }
    }
}

3.误区总结:

  账户在这一问题中就算是多线程问题中的共享资源,在线程实现类中,我们需要使用构造函数的方式将该资源定义到该类的构造函数里,在具体多线程操作时创建唯一的资源,并将其放入新建线程的构造函数中,这样就能实现模拟多个线程操作同一资源的效果。

原文地址:https://www.cnblogs.com/g177w/p/9909340.html

时间: 2024-10-07 05:27:22

关于java多线程任务执行时共享资源加锁的方式思考的相关文章

使用JVMTI获取Java多线程程序指令执行次序

使用JVMTI获取Java多线程程序指令执行次序 在Java多线程程序中,由于线程调度,指令间的次序在每次运行时都可能不相同,有时候,我们需要得到指令次序,用来分析程序的行为.这样细粒度的底层行为用一般方法很难完成,我们需要借助 JVM Tool Interface,即JVMTI,来帮助我们获取Java虚拟机执行时的信息.本文先介绍编写JVMTI程序的基本框架,然后介绍如何使用JVMTI来获取多线程程序中指令之间的次序. JVMTI简介 JVMTI是用于编写开发与监视工具的编程接口,使用它可以检

共享资源加锁的操作方法-10-多线程

1 在多线程的编程环境中,锁的使用必不可少! 2 于是,今天来总结一下为共享资源加锁的操作方法. 3 4 一.使用synchronized方式 5 6 //线程1 7 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 8 @synchronized(_myLockObj){ 9 [obj1 method1]; 10 sleep(30); 11 } 12 @synchronized(ob

java内存结构(执行时数据区域)

java虚拟机规范规定的java虚拟机内存事实上就是java虚拟机执行时数据区,其架构例如以下: 当中方法区和堆是由全部线程共享的数据区. Java虚拟机栈.本地方法栈和程序计数器是线程隔离的数据区. (1).程序计数器: 是一块较小的内存空间,其作用能够看作是当前线程所运行的字节码的行号指示器,字节码解析器工作时通过改变程序计数器的值来选取下一条须要运行的字节码指令. 程序的分支.循环.跳转.异常处理以及线程恢复等基础功能都是依赖程序计数器来完毕. Java虚拟机的多线程是通过线程轮流切换并分

Java多线程编程:变量共享分析(Thread)

在编写多线程程序时,最重要的就是搞清楚哪些变量是共享的,哪些变量是不共享的.也就是要分析清楚其中的原理呀. 因为最近要使用多线程就看了一些,对使用Thread类的子类创建线程的情况,总结如下: 1.方法体内部定义的局部变量不共享 这是因为方法内部定义的变量是在运行时动态生成的.每个线程都有一个自己的堆栈,用于保存运行时的数据. 最容易理解的就是递归调用时候,每次的入栈出栈操作.如下,每次调用时,变量aa都是在运行时堆栈上保存的,方法结束变量也就释放了. public int fib(int n)

Java多线程~~~使用信号量来控制资源获取

在多线程开发中,有一个很经典的名词,那就是信号量.信号量就是用来衡量一个资源的可利用数目的,根据信号 量的多少来控制在多线程中各个资源之间的冲突问题,在Java中也提供了对信号量的支持. 而且在创建信号量的时候,第二个参数用来指定采取何种分配策略,比如当有很多线程被阻塞,但有一个机会的时 候,信号量应该选择谁去运行呢,如果选择true,就采用公平模式,到时候看哪个线程等待的时间最久,就把机会给那 个等待最久的线程,这样的就是公平分配策略. 下面就用代码来说明一下问题 package com.bi

Java多线程编程5--定时器Timer的使用

定时/计划功能在移动开发领域使用较多,比如Android技术.定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以它和线程技术还是有非常大的关联的. 在JDK库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务. Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类 执行计划任务的代码要放人TimerTask的子类中,因为TimerTask是一个抽象类. schedule (TimerTask task

java多线程批量执行的时限问题

需求:需要并发执行三个线程,要求在指定的时间内返回结果,如果某个线程超时,则返回为空. 思路:使用ExecutorService的invokeAll(time,timeUint)方法来设置执行时限,该方法返回一个List<Future<T>>,一旦返回后,即取消尚未完成的任务,然后再从list中读取future并调用future.get()方法来获取线程返回的结果,如果future.get()抛出CancellationException 则说明该任务未完成被取消了. <T&

CastleActiveRecord在多线程 事务提交时数据库资源竞争导致更新失败的测试结果记录

CastleActiveRecord 经过测试,隔离级别: // 摘要: //     指定连接的事务锁定行为.    public enum IsolationLevel    {        // 摘要:         //     正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别.        Unspecified = -1,        //        // 摘要:         //     无法覆盖隔离级别更高的事务中的挂起的更改.        Chaos 

Java多线程Thread使用匿名内部类创建的两种方式

匿名内部类实现线程的两种方式: 第一种方式: 1.继承Thread类 2.重写run方法 3.将要执行的代码写在run方法中 第二种方式: 1.将Runnable的子类对象传递给Thread的构造方法 2.重写run方法 3.将执行的代码写在run方法中,最后我们开启线程 package com.yyx.thread; /** * 匿名内部类创建线程 yyx 2018年2月4日 */ public class AnonymousThread { public static void main(S