线程的同步

线程的同步:

  由于同一进程的多个线程共享存储空间,在带来方便的同时也带来访问冲突的问题。例如在本例中若两个线程同时访问变量balance,会造成结果不符合实际要求的情况,在本例中描述为:一个账号余额为1000元,两个或多个线程同时进行取款1000元操作,但取款操作后结果出现余额为负数,这与实际情况余额应该大于0元的结果不符。

  在java中引入了“对象互斥锁”的概念来实现对不同线程的共享数据操作的同步。“对象互斥锁”不允许多个线程同时访问同一个条件变量(即共享数据)。实质上,是把多个线程对象并行的访问数据共享改为串行的访问数据,即同一时刻最多只有一个对象访问共享数据。

  java中针对方法提出一套机制,就是synchronized关键字,它包括两种用法:synchronized修饰方法和synchronized修饰程序块。

本例中定义了3个类:
Bank(定义银行账号),Operation(线程类,实现存/取款操作)和TestBankOperation(主类)
本例中实现线程同步的方法:
1)给public void deposite(double dmount)和 public void withdrawal(double dmount)方法加锁,
即加上关键字 synchronized
2)在取款和存款的过程中给bank对象加锁

public class TestBankOperation {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Bank bank = new Bank("1002",1000);
        //创建线程的方法一:继承Thread类
        new Operation(1+"# ",bank,1000).start();
        new Operation(0+"# ",bank,1000).start();
        new Operation(3+"# ",bank,1000).start();
        /*
        //创建线程的方法二:实现Runnable接口
        Operation o = new Operation("#",bank,1000);
        Thread t1 = new Thread(o);
        Thread t2 = new Thread(o);
        Thread t3 = new Thread(o);
        t1.start();
        t2.start();
        t3.start();
        */
    }
}

/*
 *线程类,实现了同步取款操作
 */
class Operation extends Thread
//class Operation implements Runnable
{
    Bank bank;
    double mount;
    String name;
    public Operation(String name)
    {
        super(name);
        //this.name = name;
    }
    public Operation(String name,Bank bank,double dmount)
    {
        super(name);
        //this.name = name;
        this.bank = bank;
        this.mount = dmount;
    }
    /*
    public void run()
    {
        //bank.deposite(mount);
        bank.withdrawal(mount);
    }
    */
    public void run()
    {
        synchronized(bank)
        {
            bank.withdrawal(mount);
        }
    }
}
/*
 * 银行账号类
 */
class Bank
{

    String account;//账号
    double balance;//余额
    Bank(String account,double balance)
    {
        this.setAccount(account);
        this.balance = balance;
    }
    //设置账号
    public void setAccount(String account)
    {
        this.account = account;
    }
    //设置余额
    public void setBalance(double balance)
    {
        this.balance = balance;
    }
    //获取账号
    public String getAccount()
    {
        return this.account;
    }
    //获取余额
    public double getBanlance()
    {
        return this.balance;
    }
    /*
     * 存款
     * @param dmount存款金额
     */
    public void deposite(double dmount)
    //public synchronized void deposite(double dmount)
    {
        this.setBalance(this.getBanlance()+dmount);
        System.out.println(Thread.currentThread().getName()+"线程存款成功!  "+"存款为:" + dmount + "   当前余额为:" + this.balance+"\n");
    }

    /*
     * 取款操作
     * @param dmount 取款金额
     */
    public void withdrawal(double dmount)
    //public synchronized void withdrawal(double dmount)
    {
        if(dmount <= this.balance)
        {
            System.out.println(Thread.currentThread().getName()+"线程取款成功!  "+"吐出钞票为:" + dmount);
            this.setBalance(this.balance-dmount);
            System.out.println("当前余额为:" + this.balance+"\n");
        }
        else
            System.out.println("余额不足!");
    }

}

某次运行结果:

线程的同步,布布扣,bubuko.com

时间: 2024-10-25 09:59:04

线程的同步的相关文章

Linux环境下线程消息同步的陷阱

我们程序中常常会使用到线程间的消息同步处理,比如以下一段伪码 var message = "": void func()  {   1. 启动线程Thread(该线程中填充message的内容):   2. 阻塞,直到等待到完成message填充的事件:   3. 处理message:   .... } void Thread()  {   1. 通过某种处理填充message:   2. 触发func中的阻塞事件: } 我们通常会使用条件变量来完成类似情况的线程同步处理 比如wind

线程+任务+同步

线程: 对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务.一个进程的多个线程可以同时运行在不同的CPU上或多核CPU的不同内核上. 线程是程序中独立的指令流.在VS编辑器中输入代码的时候,系统会分析代码,用下划线标注遗漏的分号和其他语法错误,这就是用一个后台线程完成.Word文档需要一个线程等待用户输入,另一个线程进行后台搜索,第三个线程将写入的数据存储在临时文件中.运行在服务器上的应用程序中等待客户请求的线程成为侦听器线程.

线程间同步之信号量实现环形buf

一.概述: 信号量是一个非负整数的计数器,它通过计数器来实现多线程对临界资源的顺序访问,从而实现线程间的同步.它与进程间通信的信号量不同,进程间通信的信号量是一个信号量集,而线程间同步的信号量是一个信号.还有一点,就是对信号量的操作是原子的. 信号量与互斥锁的区别: (1).互斥锁的值只能是0或1,而信号量的值为非负整数. (2).互斥锁用与实现线程间的互斥,而信号量用于实现线程间的同步. (3).互斥锁的加锁和解锁必须由同一个线程分别对应使用,而信号量可以由一个线程得到,另一个线程释放. 下面

线程的同步与互斥,死锁

线程的同步与互斥 多个线程同时访问共享数据时可能会发生冲突,比如两个线程同时把一个全局变量加1,结果可能不是我们所期待的: 我们看这段代码的执行结果: #include <stdio.h> #include <stdlib.h> #include <pthread.h> static int g_count=0; void *thread(void *arg) { int index=0; int tmp=0; while(index++<5000) { tmp=

线程和同步

线程和同步 1 概述 对于所有需要等待 的操作,例 如 ,因 为文件 . 数据库或网络访 问都需要一定 的时间,此 时就可以启 动一个新线程,同时完成其他任务,即使是处理密集型的任务,线程也是有帮助的. 2 Parallel类 2.1 用Parallel.For()方法循环 Parallel.For()方法类似于C#的For循环,多次执行一个任务,它可以并行运行迭代.迭代的顺序没有定义. 1 ParallelLoopResult result = Parallel.For(0, 10, i =>

第二十八(线程的同步、守护线程、Timer 定时器)

/* 模拟ATM取款,不是线程同步机制,多线程同时对一个账户进行操作 t1 和 t2 异步编程模型:t1线程执行t1,t2线程执行的是t2,两个线程之间谁也不等于谁 同步编程模型:t1线程和t2线程执行,当t1线程必须等于t2的线程执行结果之后,t1线程才能执行 这是同步编程模型. 什么时候需要引入同步 1. 为了数据安全,尽管应用程序的使用率低,但是为了保证数据安全性,必须的加入线程同步机制 线程同步机制 使程序变成了(等同)单线程 2. 在什么条件下需要使用线程同步 <1> 必须是多线程环

Java线程:线程的同步与锁

一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public class Foo {     private int x = 100; public int getX() {         return x;     } public int fix(int y) {         x = x - y;         return x;     } }

线程的同步synchronized

一个Java程序的多线程之间可以共享数据. 当线程以异步方式访问共享数据时,有时候是不安全的或者不和逻辑的.比如卖火车票,同一时刻一个线程在读取数据,另外一个线程在处理数据,当处理数据的线程没有等到读取数据的线程读取完毕就去处理数据,必然得到错误的处理结果. 卖火车票Demo: class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;

Java并发编程:线程的同步

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Java线程:线程的同步与锁

1.同步和锁 java中每个对象都有一个内置锁,程序执行非静态的synchronized同步方法时,自动获得执行该方法的对象有关的锁. 一个对象只有一个锁,当一个线程获得锁,其他线程不能进入该对象上的synchronized方法或代码块.直到锁被释放. 线程可以有多个锁,例如,一个对象的同步方法中调用另一个对象的同步方法 2.静态方法的同步 同步静态方法,用的是类对象的锁,即xx.class. 3.线程安全类 对类中的方法进行了同步,但操作这个类时仍然不一定安全. 例如: public  cla