线程同步

多线程并发运行不确定性问题解决方案:引入线 程同步机制,使得另一线程要使用该方法,就只 能等待。

⚫ 在Java中解决多线程同步问题的方法有两种:

1.- Java SE 5.0中引入ReentrantLock类(P648页)。

2.- 在共享内存的类方法前加synchronized修饰符。

……

public synchronized static void sub(int m)

……

解决方案一:锁对象与条件对象

用ReentrantLock保护代码块的基本结构如下:

myLock.lock();

try {

   critical section

} finally{

myLock.unlock(); }

有关锁对象和条件对象的关键要点:

➢ 锁用来保护代码片段,保证任何时刻只能有一 个线程执行被保护的代码。

➢ 锁管理试图进入被保护代码段的线程。

➢ 锁可拥有一个或多个相关条件对象。

➢ 每个条件对象管理那些已经进入被保护的代码 段但还不能运行的线程。

解决方案二: synchronized关键字

synchronized关键字作用:

➢ 某个类内方法用synchronized 修饰后,该方法被称为同步方法;

➢ 只要某个线程正在访问同步方法,其他线程欲要访问同步方法就被阻塞,直至线程从同步方法返回前唤醒被阻塞线程,其他线程方可能进入同步方法。

➢ 一个线程在使用的同步方法中时,可能根据问题的需要,必须使用wait()方法使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。

➢ 线程如果用完同步方法,应当执行notifyAll()方 法通知所有由于使用这个同步方法而处于等待的 线程结束等待。

第二部分:实验部分——线程同步控制

实验时间 2018-12-10

1、实验目的与要求

(1) 掌握线程同步的概念及实现技术;

(2) 线程综合编程练习

2、实验内容和步骤

实验1:测试程序并进行代码注释。

测试程序1:

1.在Elipse环境下调试教材651页程序14-7,结合程序运行结果理解程序;

2.掌握利用锁对象和条件对象实现的多线程同步技术。

package synch;

import java.util.*;
import java.util.concurrent.locks.*;

/**
一个银行有许多银行帐户,使用锁序列化访问 * @version 1.30 2004-08-01
* @author Cay Horstmann
*/
public class Bank
{
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;

/**
* 建设银行。
* @param n 账号
* @param initialBalance 每个账户的初始余额
*/
public Bank(int n, double initialBalance)
{
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}

/**
* 把钱从一个账户转到另一个账户。
* @param 从账户转账
* @param 转到要转账的账户
* @param 请允许我向你转达
*/
public void transfer(int from, int to, double amount) throws InterruptedException
{
bankLock.lock();
try
{
while (accounts[from] < amount)
sufficientFunds.await();
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
sufficientFunds.signalAll();
}
finally
{
bankLock.unlock();
}
}

/**
* 获取所有帐户余额的总和。
* @return 总余额
*/
public double getTotalBalance()
{
bankLock.lock();
try
{
double sum = 0;

for (double a : accounts)
sum += a;

return sum;
}
finally
{
bankLock.unlock();
}
}

/**
* 获取银行中的帐户数量。
* @return 账号
*/
public int size()
{
return accounts.length;
}
}

package synch;

/**
* 这个程序显示了多个线程如何安全地访问数据结构。
* @version 1.31 2015-06-21
* @author Cay Horstmann
*/
public class SynchBankTest
{
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
public static final double MAX_AMOUNT = 1000;
public static final int DELAY = 10;

public static void main(String[] args)
{
Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
for (int i = 0; i < NACCOUNTS; i++)
{
int fromAccount = i;
Runnable r = () -> {
try
{
while (true)
{
int toAccount = (int) (bank.size() * Math.random());
double amount = MAX_AMOUNT * Math.random();
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
}
catch (InterruptedException e)
{
}
};
Thread t = new Thread(r);
t.start();
}
}
}

测试程序2:

l 在Elipse环境下调试教材655页程序14-8,结合程序运行结果理解程序;

l 掌握synchronized在多线程同步中的应用。

实验代码:

package synch2;

import java.util.*;

/**
* A bank with a number of bank accounts that uses synchronization primitives.
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
public class Bank
{
private final double[] accounts;

/**
* Constructs the bank.
* @param n the number of accounts
* @param initialBalance the initial balance for each account
*/
public Bank(int n, double initialBalance)
{
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
}

/**
* Transfers money from one account to another.
* @param from the account to transfer from
* @param to the account to transfer to
* @param amount the amount to transfer
*/
public synchronized void transfer(int from, int to, double amount) throws InterruptedException
{
while (accounts[from] < amount)
wait();
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
notifyAll();
}

/**
* Gets the sum of all account balances.
* @return the total balance
*/
public synchronized double getTotalBalance()
{
double sum = 0;

for (double a : accounts)
sum += a;

return sum;
}

/**
* Gets the number of accounts in the bank.
* @return the number of accounts
*/
public int size()
{
return accounts.length;
}
}

  1. package synch2;
  2.  
  3. /**
  4. * This program shows how multiple threads can safely access a data structure,
  5. * using synchronized methods.
  6. * @version 1.31 2015-06-21
  7. * @author Cay Horstmann
  8. */
  9. public class SynchBankTest2
  10. {
  11. public static final int NACCOUNTS = 100;
  12. public static final double INITIAL_BALANCE = 1000;
  13. public static final double MAX_AMOUNT = 1000;
  14. public static final int DELAY = 10;
  15.  
  16. public static void main(String[] args)
  17. {
  18. Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
  19. for (int i = 0; i < NACCOUNTS; i++)
  20. {
  21. int fromAccount = i;
  22. Runnable r = () -> {
  23. try
  24. {
  25. while (true)
  26. {
  27. int toAccount = (int) (bank.size() * Math.random());
  28. double amount = MAX_AMOUNT * Math.random();
  29. bank.transfer(fromAccount, toAccount, amount);
  30. Thread.sleep((int) (DELAY * Math.random()));
  31. }
  32. }
  33. catch (InterruptedException e)
  34. {
  35. }
  36. };
  37. Thread t = new Thread(r);
  38. t.start();
  39. }
  40. }
  41. }

测试程序3:

l 在Elipse环境下运行以下程序,结合程序运行结果分析程序存在问题;

l 尝试解决程序中存在问题。

class Cbank

{

private static int s=2000;

public   static void sub(int m)

{

int temp=s;

temp=temp-m;

try {

Thread.sleep((int)(1000*Math.random()));

}

catch (InterruptedException e)  {              }

s=temp;

System.out.println("s="+s);

}

}

class Customer extends Thread

{

public void run()

{

for( int i=1; i<=4; i++)

Cbank.sub(100);

}

}

public class Thread3

{

public static void main(String args[])

{

Customer customer1 = new Customer();

Customer customer2 = new Customer();

customer1.start();

customer2.start();

}

}

修改之后如下:

import javax.sql.rowset.spi.SyncFactory;

 
class Cbank
{
     private static int s=2000;
     public synchronized static void sub(int m)
     {
           int temp=s;
           temp=temp-m;
          try {
                 Thread.sleep((int)(1000*Math.random()));
               }
           catch (InterruptedException e)  {              }
              s=temp;
              System.out.println("s="+s);
          }
    }
 
 
class Customer extends Thread
{
  public void   run()
  {
   forint i=1; i<=4; i++)
    Cbank.sub(100);
    }
 }
public class Thread3
{
 public static void main(String args[])
  {
   Customer customer1 = new Customer();
   Customer customer2 = new Customer();
   customer1.start();
   customer2.start();
  }
}

实验2 编程练习

利用多线程及同步方法,编写一个程序模拟火车票售票系统,共3个窗口,卖10张票,程序输出结果类似(程序输出不唯一,可以是其他类似结果)。

Thread-0窗口售:第1张票

Thread-0窗口售:第2张票

Thread-1窗口售:第3张票

Thread-2窗口售:第4张票

Thread-2窗口售:第5张票

Thread-1窗口售:第6张票

Thread-0窗口售:第7张票

Thread-2窗口售:第8张票

Thread-1窗口售:第9张票

Thread-0窗口售:第10张票

  1. package xaincheng;
  2.  
  3. import java.nio.charset.MalformedInputException;
  4.  
  5. public class Demo {
  6. public static void main(String[] args)
  7. {
  8. Mythread mythread= new Mythread();
  9. Thread t1 = new Thread(mythread);
  10. Thread t2 = new Thread(mythread);
  11. Thread t3 = new Thread(mythread);
  12. t1.start();
  13. t2.start();
  14. t3.start();
  15.  
  16. }
  17.  
  18. }
  19.  
  20. class Mythread implements Runnable{
  21.  
  22. int t=1;
  23. boolean flag=true;
  24.  
  25. public void run() {
  26.  
  27. while(flag) {
  28. try {
  29.  
  30. Thread.sleep(500);
  31. }
  32. catch (InterruptedException e)
  33. {
  34. e.printStackTrace();
  35. }
  36.  
  37. synchronized (this) {
  38.  
  39. if(t<=10){
  40. System.out.println(Thread.currentThread().getName()+"窗口售:第"+t+"张票");
  41. t++;
  42. }
  43. if(t>10){
  44. flag=false;
  45. }
  46.  
  47. }
  48.  
  49. }
  50. }
  51. }

  1. 实验总结:通过本学期对Java这门课程的学习收获了很多,也很感谢老师还有助教学长对我们无微不至的关心,也通过这次试验加深了对多线程的理解,知道了并发多线程的解决方法。
  1.  

周强 201771010141面向对象程序设计(java)》第十七周学习总结的更多相关文章

  1. 201771010134杨其菊《面向对象程序设计java》第九周学习总结

                                                                      第九周学习总结 第一部分:理论知识 异常.断言和调试.日志 1.捕获 ...

  2. 201771010141 周强《面向对象程序设计(java)》第十三周学习总结

    实验目的与要求 (1) 掌握事件处理的基本原理,理解其用途: (2) 掌握AWT事件模型的工作机制: (3) 掌握事件处理的基本编程模型: (4) 了解GUI界面组件观感设置方法: (5) 掌握Win ...

  3. 扎西平措 201571030332《面向对象程序设计 Java 》第一周学习总结

    <面向对象程序设计(java)>第一周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ...

  4. 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结

    面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...

  5. 201771010141 周强《面向对象设计 java》第十五周实验总结

    理论部分 ◼ JAR文件◼ 应用程序首选项存储◼ Java Web Start JAR文件: 1.Java程序的打包:程序编译完成后,程序员将.class文件压缩打包为.jar文件后,GUI界面程序就 ...

  6. 201871010115——马北《面向对象程序设计JAVA》第二周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  7. 杨其菊201771010134《面向对象程序设计Java》第二周学习总结

    第三章 Java基本程序设计结构 第一部分:(理论知识部分) 本章主要学习:基本内容:数据类型:变量:运算符:类型转换,字符串,输入输出,控制流程,大数值以及数组. 1.基本概念: 1)标识符:由字母 ...

  8. 201871010124 王生涛《面向对象程序设计JAVA》第一周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://edu.cnblogs.com/campus/xbsf/ ...

  9. 面向对象程序设计--Java语言第二周编程题:有秒计时的数字时钟

    有秒计时的数字时钟 题目内容: 这一周的编程题是需要你在课程所给的时钟程序的基础上修改而成.但是我们并不直接给你时钟程序的代码,请根据视频自己输入时钟程序的Display和Clock类的代码,然后来做 ...

随机推荐

  1. Web的Flex弹性盒模型

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. sql获取当前月份的前一月,当前天的前一天,当前年的前一年

    当前年份加减: SELECT CONVERT(varchar(12),DATEADD(year,1,GETDATE()),23) as year SELECT CONVERT(varchar(12), ...

  3. <!--#include virtual='head.html'-->代码复用

    js限制input框只能输入数字:<input type="text" onkeyup="value=value.replace(/[^\d]/g,'')" ...

  4. 【分享】谈CSS3中display属性的flex布局

    最近在学习微信小程序(重新学习微信小程序),在设计首页布局的时候,新认识了一种布局方式display:flex .guide-top{ height: 36%; display: flex; /*fl ...

  5. C# 今天时间 今天结束时间

    var startTime = DateTime.UtcNow.ToString(timeFormat); ).AddSeconds(-).ToUniversalTime().ToString(tim ...

  6. Netty(一)——Netty入门程序

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7447618.html 有兴趣的可先了解下:4种I/O的对比与选型 主要内容包括: Netty开发环境的搭建 ...

  7. C++文件输入和创建

    #include <fstream> //头文件 ifstream inf; ofstream ouf; inf.open("zy4.txt", ios::out); ...

  8. SpringBoot 下 mybatis 的缓存

    背景: 说起 mybatis,作为 Java 程序员应该是无人不知,它是常用的数据库访问框架.与 Spring 和 Struts 组成了 Java Web 开发的三剑客--- SSM.当然随着 Spr ...

  9. 一个简单的windows勒索软件分析

    根据分析,此病毒是一个勒索软件,通过修改登录用户密码,留下勒索QQ号码向用户索要金钱. 它调用了Kernel32.dll里的WinExec来执行更改用户密码的cmd命令,密码为107289,更改完密码 ...

  10. flask 第二章 endpoint重名 Flask路由 初始化配置 Falsk Config 蓝图+目录结构

    今日内容 1.路由的分发,以下两种方式效果一样,但是都能指向同一个函数 from flask import Flask app=Flask(__name__) #第一种方式 @app.route('/ ...