Java语言描述进程基本概念

来源:互联网 发布:centos复制文件夹命令 编辑:程序博客网 时间:2024/05/18 03:40


1  线程的异步性

线程的异步性是由于多个线程异步的并发修改同一数据引起的。以下代码创建了100个线程,每个线程异步的向account对象中增加1分钱,运行该程序会发现最终结果并非100,而且每次运行结果都不相同。通过该程序可使学生直观的观察到线程异步性的问题,教师

import java.util.concurrent.*;

public class AccountWithoutSync {

 private static Account account = new Account();

 public static void main(String[] args) {

   ExecutorService executor = Executors.newCachedThreadPool();

   // Create and launch 100 threads

   for (int i = 0; i < 100; i++) {

     executor.execute(new AddAPennyTask()); }

   executor.shutdown();

   // Wait until all tasks are finished

   while (!executor.isTerminated()) { }

   System.out.println("What is balance? " + account.getBalance());}

  //A thread for adding a penny to the account

 private static class AddAPennyTask implements Runnable {

   public void run() {

     account.deposit(1); } }

  //An inner class for account

 private static class Account {

   private int balance = 0;

   public int getBalance() {

     return balance; }

   public void deposit(int amount) {

     int newBalance = balance + amount;

     // This delay is deliberately added to magnify the

     // data-corruption problem and make it easy to see.

      try{                                   

       Thread.sleep(5); }

     catch (InterruptedException ex) { }

     balance = newBalance; } } }

可在此基础上提出竞争条件和临界区等基本概念,然后引入同步机制解决该代码的异步问题,如此学生可深刻意识到操作系统理论解决实际问题的重要性,产生对后续理论深入学习的兴趣。

2  信号量

信号量(Semaphore)由Edsger Dijkstra于60年代提出,其主要用于限制访问共享资源的线程数目[1],Java语言中的Semaphore类即是信号量概念的具体实现,其用法如下:

Semaphore sem = new Semaphore(n);

try{

  sem.acquire();  //P操作

   //critical section

}catch(InterruptedException ie){ }

finally{

  sem.release();  //V操作

}

   //remainder section

教师可在介绍其内部实现原理后,让学生用二元信号量(binarysemaphore)解决2.1中的代码异步问题,立即将理论应用于实践,以加深对理论的理解。

3  管程

管程(Monitor)是由Brinch Hansen和Tony Hoare于70年代提出的一种高级同步原语[2],寻常系统中已很少看到具体实现,以至许多学生甚至教师认为其仅是理想化的概念,所以通过伪语言很难向学生阐明其便利性和高效性。其实Java语言提供的synchronized同步锁即为管程的实现,Java语言的每个对象都有一个隐含锁(Lock)和一个内置条件变量(Condition),如图1所示,等待获取对象锁的线程都在该对象的进入队列(entry set)中,因条件变量阻塞的线程都在该条件所对应的队列(wait set)中。


图1  Java语言实现的管程结构图

管程的发明者Brinch Hansen于1999年曾撰文对Java语言的管程的实现提出了中肯的评价。以下代码利用synchronized同步锁的管程实现展示了线程间的协作关系。

//Thread1

synchronized(anObject) {

  try{

    //Wait for the condition to become true

    while (!condition)

      anObject.wait();

   //Do something when condition is true

}catch (InterruptedException ex) {

   ex.printStackTrace(); } }

//Thread2

synchronized(anObject) {

  //When condition becomes true

  anObject.notify(); //oranObject.notifyAll(); }

0 0
原创粉丝点击