• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > Java线程同步、同步方法实例详解

Java线程同步、同步方法实例详解

作者:在奋斗的大道 字体:[增加 减小] 来源:互联网 时间:2017-05-28

在奋斗的大道 通过本文主要向大家介绍了java多线程详解,java线程池详解,java线程详解,java多线程编程详解,java中的线程详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

线程的同步是保证多线程安全访问竞争资源的一种手段。

线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源、什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些原则问题需要考虑,是否有竞争资源被同时改动的问题?

对于同步,在具体的Java代码中需要完成一下两个操作:

把竞争访问的资源标识为private;

同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。

当然这不是唯一控制并发安全的途径。

 synchronized关键字使用说明

synchronized只能标记非抽象的方法,不能标识成员变量。 

为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,

禁止直接访问。

/** 
* Java线程:线程的同步 
* 
* @author leizhimin 2009-11-4 11:23:32 
*/ 
public class Test { 
  public static void main(String[] args) { 
    User u = new User("张三", 100); 
    MyThread t1 = new MyThread("线程A", u, 20); 
    MyThread t2 = new MyThread("线程B", u, -60); 
    MyThread t3 = new MyThread("线程C", u, -80); 
    MyThread t4 = new MyThread("线程D", u, -30); 
    MyThread t5 = new MyThread("线程E", u, 32); 
    MyThread t6 = new MyThread("线程F", u, 21); 
    t1.start(); 
    t2.start(); 
    t3.start(); 
    t4.start(); 
    t5.start(); 
    t6.start(); 
  } 
} 
class MyThread extends Thread { 
  private User u; 
  private int y = 0; 
   MyThread(String name, User u, int y) { 
    super(name); 
    this.u = u; 
    this.y = y; 
  } 
  public void run() { 
    u.oper(y); 
  } 
} 
class User { 
  private String code; 
  private int cash; 
  User(String code, int cash) { 
    this.code = code; 
    this.cash = cash; 
  } 
  public String getCode() { 
    return code; 
  } 
  public void setCode(String code) { 
    this.code = code; 
  } 
  /** 
   * 业务方法 
   * @param x 添加x万元 
   */ 
  public synchronized void oper(int x) { 
    try { 
      Thread.sleep(10L); 
      this.cash += x; 
      System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash); 
      Thread.sleep(10L); 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } 
  } 
  @Override 
  public String toString() { 
    return "User{" + 
        "code='" + code + '\'' + 
        ", cash=" + cash + 
        '}'; 
  } 
} 
</div>

输出结果:

线程A运行结束,增加“20”,当前用户账户余额为:120 
线程F运行结束,增加“21”,当前用户账户余额为:141 
线程E运行结束,增加“32”,当前用户账户余额为:173 
线程C运行结束,增加“-80”,当前用户账户余额为:93 
线程B运行结束,增加“-60”,当前用户账户余额为:33 
线程D运行结束,增加“-30”,当前用户账户余额为:3 
</div>

反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:

线程A运行结束,增加“20”,当前用户账户余额为:61 
线程D运行结束,增加“-30”,当前用户账户余额为:63 
线程B运行结束,增加“-60”,当前用户账户余额为:3 
线程F运行结束,增加“21”,当前用户账户余额为:61 
线程E运行结束,增加“32”,当前用户账户余额为:93 
线程C运行结束,增加“-80”,当前用户账户余额为:61 
</div>

很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动。

可见同步的重要性。 

注意:

通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类。

void notify()  
     唤醒在此对象监视器上等待的单个线程。  
void notifyAll()  
     唤醒在此对象监视器上等待的所有线程。  
void wait()  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。  
void wait(long timeout)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。  
void wait(long timeout, int nanos)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量 
</div>

结合以上方法,处理多线程同步与互斥问题非常重要,著名的生产者-消费者例子就是一个经典的例子,任何语言多线程必学的例子。 

希望本篇文章对小伙伴们有所帮助

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Java 回调函数详解及使用
  • java 同步器SynchronousQueue详解及实例
  • Java可变参数列表详解
  • Java中终止线程的方法详解
  • Java中的对象和引用详解
  • java回调机制实例详解
  • Java多线程中线程间的通信实例详解
  • Java实现一个达达租车系统的步骤详解
  • Java内存分布归纳整理详解
  • Java 线程优先级详解及实例

相关文章

  • 2017-05-28java判断ftp目录是否存在的方法
  • 2017-05-28Spring Boot使用和配置Druid
  • 2017-05-28Java爬虫Jsoup+httpclient获取动态生成的数据
  • 2017-05-28详解java中保持compareTo和equals同步
  • 2017-05-28简单谈谈RxJava和多线程并发
  • 2017-05-28Java基于正则实现的日期校验功能示例
  • 2017-05-28java版简单的猜数字游戏实例代码
  • 2017-05-28spring+hibernate 两种整合方式配置文件的方法
  • 2017-05-28AspectJ的基本用法
  • 2017-05-28java数据结构与算法之简单选择排序详解

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Java 运算符 动力节点Java学院整理
    • java WSDL接口webService实现方式
    • Java 中的 BufferedReader 介绍_动力节点Java学院整理
    • 通过Session案例分析一次性验证码登录
    • 详解Java中-classpath和路径的使用
    • java中重写equals和重写hashCode()
    • 详解springboot+mybatis多数据源最简解决方案
    • 详解Spring Boot使用redis实现数据缓存
    • response.setHeader各种用法详解
    • Spring Boot 之HelloWorld开发案例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有