您的位置:首页 > 编程语言 > Java开发

Java 并发编程学习笔记(1)--线程的同步1

2018-01-18 21:32 155 查看
多线程程序中,经常会遇到多个线程需要共享一对数据的存取。当两个线程存取相同的对象,并且每一个线程都调用了一个修改该对象状态的方法,可能导致讹误。这样的情况称为竞争条件。
1.使用ReentrantLock保护代码块

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
*/
public class bank
{
private final double[] account ;
private Lock banklock ;
private Condition suffcientFunds;
public bank(int n,double initialBlance){
account = new double
;
Arrays.fill(account,initialBlance);
banklock = new ReentrantLock(); //声明一个显示锁

}
public void transfer(int from, int to,double amount)
{
banklock.lock();
//在共享资源前 发布线程 锁
try
{

System.out.println(Thread.currentThread());
account[from] -= amount;
System.out.printf("%10.2f from %d to %d",amount,from,to);
account[to] += amount;
System.out.printf("Total Balance :%10.2f%n",getTotalBlance());

}
catch (Exception e)
{

}
finally {
{
banklock.unlock();
//加锁同样需要解锁
}
}
}
public double getTotalBlance()
{
banklock.lock();
try {
double sum =0;
for (double a:account)sum+=a;
return sum;
}
finally {
banklock.unlock();
}
}
public int size()
{
return account.length;
}
}
import java.util.*;
import java.lang.*;

public class main
{
public static  final  int    NACCOUNTS = 100;
public static  final  double INTIAL_BLANCE = 1000;
public static  final  double MAX_AMOUNT =1000;
public static  final  int    Dealay =10;

public static void main(String[] args)
{

bank aim1 = new bank(NACCOUNTS,INTIAL_BLANCE);
//一共会开启100个线程 每个账户是一个线程  会随机给其余账户打钱
for (int i =0;i<NACCOUNTS;i++)
{
int fromAccount = i;
Runnable r = () ->{
try
{
while(true)
{
int toAcccount = (int)(aim1.size()*Math.random());
double amount = MAX_AMOUNT*Math.random();
aim1.transfer(fromAccount,toAcccount,amount);
Thread.sleep((int) (Dealay * Math.random()));

}
}catch (InterruptedException e)
{

}
};
Thread t = new Thread(r);
t.start();
}

}

}


以上的程序中,每一个bank对象有自己的ReentrantLock对象。如果两个线程试图访问同一个Bank对象,锁就以串行方式提供服务。但是如果两个线程访问不同bank对象,每个线程得到不同的对象锁,两个线程就不会阻塞。2.条件对象
import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
*/
public class bank
{
private final double[] account ;
private Lock banklock ;
private Condition suffcientFunds;
public bank(int n,double initialBlance){
account = new double
;
Arrays.fill(account,initialBlance);
banklock = new ReentrantLock(); //声明一个显示锁
suffcientFunds = banklock.newCondition(); //条件锁
}
public void transfer(int from, int to,double amount)
{
banklock.lock();
//在共享资源前 发布线程 锁
try
{
while(account[from]<amount)
suffcientFunds.await();
//条件锁

System.out.println(Thread.currentThread());
account[from] -= amount;
System.out.printf("%10.2f from %d to %d",amount,from,to);
account[to] += amount;
System.out.printf("Total Balance :%10.2f%n",getTotalBlance());

suffcientFunds.signalAll();
//释放条件 等待
}
catch (Exception e)
{

}
finally {
{
banklock.unlock();
//加锁同样需要解锁
}
}
}
public double getTotalBlance()
{
banklock.lock();
try {
double sum =0;
for (double a:account)sum+=a;
return sum;
}
finally {
banklock.unlock();
}
}
public int size()
{
return account.length;
}
}
线程进入临界去后,通常会发现在满足某一条件后才会执行。一个锁对象可以有一个或者多个相关对象。可以用newCondition方法获得一个条件对象。调用await方法,会阻塞当前线程,会进入该条件的等待集。当锁可用时,该线程不能马上接触阻塞,要等待其他线程调用同意条件上的signalAllwhile(!ok)condition.await  采用这样的形式。
3.synchronized关键词
一个方法调用该关键词,对象的锁将保护整个方法。内部对象锁只有一个相关条件。wait方法添加一个线程到等待集中,notifyALL/notify方法解除等待线程的阻塞状态。
package com.qunar.com.www;

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
*/
public class bank
{
private final double[] account ;
private Lock banklock ;
private Condition suffcientFunds;
public bank(int n,double initialBlance){
account = new double
;
Arrays.fill(account,initialBlance);
banklock = new ReentrantLock(); //声明一个显示锁
suffcientFunds = banklock.newCondition(); //条件锁
}
public synchronized void transfer(int from, int to,double amount)
{

try
{
while(account[from]<amount)
wait();
//条件锁

System.out.println(Thread.currentThread());
account[from] -= amount;
System.out.printf("%10.2f from %d to %d",amount,from,to);
account[to] += amount;
System.out.printf("Total Balance :%10.2f%n",getTotalBlance());

notifyAll();
//释放条件 等待
}
catch (Exception e)
{

}
finally {
{

}
}
}
public double getTotalBlance()
{
banklock.lock();
try {
double sum =0;
for (double a:account)sum+=a;
return sum;
}
finally {
banklock.unlock();
}
}
public int size()
{
return account.length;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: