初探多线程之线程同步_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 初探多线程之线程同步

初探多线程之线程同步

 2015/2/3 18:25:12  w62268458  程序员俱乐部  我要评论(0)
  • 摘要:1.synchronized同步代码块synchronized(obj){.....//同步代码块的代码}直接对obj对象同步监听,任何线程在修改指定的资源之前,首先对该资源加锁,在加锁期间其他线程无法修改该资源。2.synchronized同步方法1)类里的对象可以被多线程安全访问publicsynchronizedvoiddraw(doubledrawAmount){if(this.balance>=drawAmount){System.out.println(Thread
  • 标签:

1.synchronized同步代码块

?? synchronized(obj){

????????? .....

???????? //同步代码块的代码

?? }

直接对obj对象同步监听,任何线程在修改指定的资源之前,首先对该资源加锁,在加锁期间其他线程无法修改该资源。

2.synchronized同步方法

? 1)类里的对象可以被多线程安全访问

?

class="java">public synchronized void  draw(double drawAmount){
		if (this.balance >= drawAmount) {
			System.out.println(Thread.currentThread().getName() + "取钱成功!吐出现金:" + drawAmount);

			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			this.balance = this.balance - drawAmount;
			System.out.println("\t余额为:" + balance);
		} else {
			System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足!");
		}
	}

?总结:

?

??? 1)synchronized可修饰方法,可修饰代码块,但不能修饰构造器,属性。

??? 2)不要对线程安全的所有方法都进行同步。

3.同步锁(Lock)

?? 显式加锁,显式解锁

?? ReentrantLock(可重入锁):一个线程可以对已被加锁的ReentrantLock锁再次加锁,ReentrantLock对象会维持一个计数器来追踪lock()方法的嵌套调用。

??

public class Account {
	
	private final ReentrantLock lock = new ReentrantLock();

	public void draw(double drawAmount) {
		//上锁
		lock.lock();
		try {
			......//操作代码
		} finally {
			//解锁
			lock.unlock();
		}
	}

}

?

?? 4.死锁问题

???? 当两个线程互相等待对方释放同步监视器时就会发生死锁,当陷入死锁,所有线程处于阻塞状态,无法继续。

??? 四个必要条件:

??? 1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。 ??? 2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。 ??? 3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。 ??? 4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。 ??? 传统的线程通信: ?????? wait():导致当前线程等待 ?????? notify():唤醒等待线程中的单个线程 ?????? notifyAll():唤醒等待线程中的所有线程
public class Account {
	private String accountNo;
	private double balance;
	private boolean flag = false;

	public Account(String accountNo, double balance) {
		this.accountNo = accountNo;
		this.balance = balance;
	}

	public int hashCode() {
		return accountNo.hashCode();
	}

	public boolean equals(Object object) {
		if (this == object) {
			return true;
		}

		if (object != null && object.getClass() == this.getClass()) {
			Account account = (Account) object;
			return account.getAccountNo().equals(account);
		}

		return false;
	}

	public String getAccountNo() {
		return accountNo;
	}

	public void setAccountNo(String accountNo) {
		this.accountNo = accountNo;
	}

	public double getBalance() {
		return balance;
	}

	public synchronized void draw(double drawAmount) {
		try {
			if (!flag) {
				wait();
			} else {
				if (this.balance >= drawAmount) {
					System.out.println(Thread.currentThread().getName()
							+ "取钱成功!吐出现金:" + drawAmount);

					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					this.balance = this.balance - drawAmount;
					System.out.println("\t余额为:" + balance);
					
					flag = false;
					notifyAll();
				} else {
					System.out.println(Thread.currentThread().getName()
							+ "取钱失败,余额不足!");
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public synchronized void deposit(double depositAmount) {
		try {
			if (flag) {
				wait();
			} else {
				System.out.println(Thread.currentThread().getName() + "存款:"
						+ depositAmount);

				balance += depositAmount;
				System.out.println("\t余额为:" + balance);
				flag = true;
				notifyAll();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
? ??? 使用Condition类控制线程通信 ??? Condition实例的方法: ?????? await():类似于隐式同步监视器上的wait()方法 ?????? signal():类似于notify()方法 ?????? signalAll():类似于notifyAll()方法
public class Account {
	private String accountNo;
	private double balance;
	private boolean flag = false;

	private final Lock lock = new ReentrantLock();
	private final Condition condition = lock.newCondition();

	public Account(String accountNo, double balance) {
		this.accountNo = accountNo;
		this.balance = balance;
	}

	public int hashCode() {
		return accountNo.hashCode();
	}

	public boolean equals(Object object) {
		if (this == object) {
			return true;
		}

		if (object != null && object.getClass() == this.getClass()) {
			Account account = (Account) object;
			return account.getAccountNo().equals(account);
		}

		return false;
	}

	public String getAccountNo() {
		return accountNo;
	}

	public void setAccountNo(String accountNo) {
		this.accountNo = accountNo;
	}

	public double getBalance() {
		return balance;
	}

	public void draw(double drawAmount) {
		lock.lock();
		try {
			if (!flag) {
				condition.await();
			} else {
				if (this.balance >= drawAmount) {
					System.out.println(Thread.currentThread().getName() + "取钱成功!吐出现金:" + drawAmount);
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					this.balance = this.balance - drawAmount;
					System.out.println("\t余额为:" + balance);

					flag = false;
					condition.signalAll();
				} else {
					System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足!");
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public synchronized void deposit(double depositAmount) {
		lock.lock();
		try {
			if (flag) {
				condition.await();
			} else {
				System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount);

				balance += depositAmount;
				System.out.println("\t余额为:" + balance);
				flag = true;
				condition.signalAll();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

}
??? 显式和隐式线程通信
  • 相关文章
发表评论
用户名: 匿名