java民航售票系统统怎么做到同步的

java中如何使用同步块?_百度知道
java中如何使用同步块?
提问者采纳
);Ticket2() {
super().com/zhidao/wh%3D450%2C600/sign=424fe4fb6baaec950a7b0e04ca2f1d3572c11dfcf69;
tc3;SynchronizedTest2{ public&nbsp.);args) {
Ticket2&nbsp.jpg" esrc="http. }}<img class="ikqb_img" src="
System.baidu.Object&void&2号售票员&quot.getName()+&e&nbsp.start();Ticket2(&run() {
while(true)
synchronized(obj)
if(count&(InterruptedException&nbsp://c.start();0)
Ticket2&);obj=new&
tc2;int&3号售票员& } /zhidao/wh%3D600%2C800/sign=ef2b211e47b8d48faba7b0e04ca2f1d3572c11dfcf69;Thread{ static&.tc3=new&nbsp.hiphotos://c;
tc1;main(String[]&
/zhidao/pic/item/1c950a7b0e04ca2f1d3572c11dfcf69;
} }}public&name) {
super(name);tc1=new&nbsp.println(&quot://c;tc2=new&)
System.start();Object();
Ticket2&);1号售票员&void&Ticket2(&quot.println(Ticket2(String& public& static&nbspclass&nbsp
提问者评价
其他类似问题
为您推荐:
其他1条回答
Object mutex = new Object();public void someMethod(){
synchronized ( mutex) { //
同步处理内容
java的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁你的位置: &&
Java多线程4—线程同步问题+火车票售票系统
Java多线程4—线程同步问题+火车票售票系统
在上一篇文章中写到了许多线程共享同一数据,这种情况在现实的生活中也是经常发生的,比如火车站的火车票售票系统。火车票售票系统是一个常年运行的系统,为了满足乘客的需求,我们不能只设一个窗口,必须设很多的售票窗口,每个售票窗口就像一个线程,它们各自运行,共同访问相同的数据——火车票的数量,下面我们用多线程模仿一下火车票售票系统:public
class TicketSystem
public static void main(String[] args)
SellThread st=new SellThread();
new Thread(st).start();new Thread(st).start();new Thread(st).start();
SellThread implements Runnable
int tickets=100;
public void run()
while(true)
if(tickets&0)
System.out.println("obj:"+Thread.currentThread().getName()+" sell tickets:"+tickets);
tickets--;
}程序输出了线程0、1、2三个线程从第100张票卖到第1张票的过程,这个程序正确的输出了。但是实际情况中火车票售票系统是常年运行的,有可能第一顾客已经买到了最后一张票,但是执行到tickets--的时候,线程切换了,这时候另外一个顾客也买最后一张票,这时候系统显示还有票,这时候这个顾客也订票了,并且也在执行到tickets--的时候,线程切换。再回去执行原来的线程,前个顾客买到了最后一张票,后一个顾客但是却买到了第0张票。显然这个是不对的。下面我们修改上面程序模拟一下:class
SellThread implements Runnable
int tickets=100;
public void run()
while(true)
if(tickets&0)
Try//让线程睡眠10毫秒,只是修改了这里
Thread.sleep(10);
} catch (InterruptedExceptione)
e.printStackTrace();
System.out.println("obj:"+Thread.currentThread().getName()+" sell tickets:"+tickets);
tickets--;
}结果的一部分如下:obj:Thread-0 sell tickets:2obj:Thread-2 sell tickets:2obj:Thread-1 sell tickets:0obj:Thread-0 sell tickets:-1 & & & &我们可以看出上面程序两次售出了第二张票,并且卖出了第0张和-1张票,显然这个结果是不对的。遇到了不对的情况,我们就应该得想办法解决它,在Java中运用同步的方法解决这个问题。 & & & &在介绍之前我们先说一下临界区,在Java中代码段访问了同一个对象或数据,那么这个代码段就叫做临界区。上面程序中run()方法中循环里面的代码就叫做临界区。我们需要对这个临界区进行保护,这样就用到了线程的同步。 & & & 在Java中线程的同步有两种方法,一种是同步块,另一种是同步方法。不管是哪种方法都用到了synchronized关键字。下面我们就修改上面的程序用实例显示一下:
class SellThread implementsRunnable
int tickets=100;
Object obj = new Object();
public void run()
while(true)
synchronized(obj)//加上一个同步关键字
if(tickets&0)
Thread.sleep(10);
} catch (InterruptedExceptione)
e.printStackTrace();
System.out.println("obj:"+Thread.currentThread().getName()+" sell tickets:"+tickets);
tickets--;
} & & 上面使用synchronized关键字的时候需要一个对象,这里的对象可以是任意对象,我们在这里选择的是Object对象,你也可以选择String类的对象。每一个对象都有一个监视器或者叫锁。当我将obj作为参数传给synchronized关键字的时候,就相当于给这段代码加了一个锁,当我执行到这段代码的时候,先判断是否加锁,如果没有加锁,先将其加锁然后执行代码。如果加锁了只能等待。等到给代码加锁的线程执行完成之后,会将锁打开。下面我们介绍同步方法,我们还是以程序的形式给出:
class SellThread implements Runnable
int tickets=100;
Object obj = new Object();
public synchronized void sell()//用关键字sychronized
//关键字标志同步方法
if(tickets&0)
Thread.sleep(10);
catch(Exception e)
e.printStackTrace();
System.out.println("sell():"+Thread.currentThread().getName()+
" sell tickets:"+tickets);
tickets--;
public void run()
while(true)
} 上面的程序用sychronized关键字直接标志的是sell()方法,我们在run()方法里调用sell()的时候,sell()方法中的代码就相当于一个整体都一起执行。但是同步方法也是使用加锁的方法进行同步的,它不像同步块那样传递一个对象,那么他是对哪个对象加的锁呢?同步方法是对程序中的this对象加锁以实现同步的。我们有时候会写一些静态的方法,这些方法也必须同步。静态方法只属于类本身,没有this对象,那么它对谁加锁呢?前面我们介绍过每一个类都有一个Class类的对象(详细介绍请看:http://blog.csdn.net/mengxiangyue/article/details/6831820),静态方法正是对这个Class类的对象进行加锁以实现同步方法的。 & & & &对于同步方法就先介绍到这里,如果有错请大家指出,希望对大家有帮助。
&&作者:孟祥月 &&
最新热门tag&#xe621; 上传我的文档
&#xe602; 下载
&#xe60c; 收藏
该文档贡献者很忙,什么也没留下。
&#xe602; 下载此文档
正在努力加载中...
Java多线程同步机制在售票系统的实现
下载积分:3000
内容提示:Java多线程同步机制在售票系统的实现
文档格式:PDF|
浏览次数:3|
上传日期: 00:03:07|
文档星级:&#xe60b;&#xe612;&#xe612;&#xe612;&#xe612;
该用户还上传了这些文档
Java多线程同步机制在售票系统的实现.PDF
官方公共微信关于Java和Scala同步机制你不知道的5个真相 - ImportNew
实际上,所有的服务器应用在多线程中都需要某种类型的同步机制。框架已经为我们做了大多数的同步的工作,这些框架包括web服务器、数据库连接客户端、消息框架等。我们可以通过Java和Scala提供的多种组件来写出可靠的多线程应用。这些组件包括,对象池、并发集合类、高级锁、执行上下文等。
为了更好的理解这个问题,接下来首先要探究最常用的同步模式:对象锁。这种机制增强了synchronized 关键字,使它成为Java编程多线程的最流行的习惯用法之一。同时,它也是许多常用复杂模式的基础,包括线程池、连接池、并发集合类等。
synchronized 关键字主要应用于以下两种情境:
作为一种改进方法,使被标记的某一方法在同一时间仅仅能被一个线程执行。
标记一个代码块为临界区块,标记后的代码块在任何时间点仅有一个线程可以执行。
#真相1:同步代码块是通过MonitorEnter和MonitorExit专用字节码指令来实现,这两个字节码指令也是官方参数的一部分。这种实现和其他的锁机制不同,在java.util.concurrent包中的一些方法(在hotspot上的实现)通过结合使用Java代码和使用sun.misc.Unsafe的实现本地调用。
这些指令运行在使用了sychronized上下文的对象上。对于sychronized方法,“this”变量会自动选择锁。对于静态方法,会将锁置于Class对象上。
Sychronized方法有时也会带来比较糟糕的结果,比如当不同的sychronized方法共享一个锁文件时,将会造成一些隐性依赖。如果遇到下面这种情况会变得更糟糕:比如在基类(甚至第三方类库)中声明了sychronized方法,然后又在派生类中增加了一个新的sychronized方法。这将造成整个类的层次结构对同步的隐性依赖,同时也会带来吞吐量的问题甚至死锁。为了避免出现这种问题,推荐使用私有对象作为锁对象,以此来避免意料之外的锁共享和lock溢出。
编译器与同步机制的关系
通过两个字节码指令负责完成同步工作是不同寻常的。通常字节码指令之间相互独立的,通过把值放在线程操作数堆栈上完成字节码之间的相互“通信”。被加锁的对象也预先放在操作数堆栈上,然后通过从变量、字段中取值或者方法反射的方式来从操作数堆栈上返回一个对象。
#真相2:如果仅仅调用两个字节码指令其中之一,而不调用另一个会出现什么情况?仅仅调用monitorExit却不调用MonitorEnter的代码,Java编译器不会编译通过的。即使从JVM角度来看这也是合理的。这种情况的结果就是MonitorExit指令会抛出一个IllegalMonitorStateException异常。
一种更加危险的情形是:如果一个锁通过调用MonitorEnter被获取却不被调用MonitorExit被释放会发生什么?这种情况下,得到锁的线程将会造成其他需要获取此锁的线程无限期挂起。这是毫无意义的。因为锁本身可重入,从某种意义上说,线程之间都是平等的。虽然这个线程现在快乐地执行着,当这个线程下次需要执行这段代码的时候,也需要重新获取这个锁。(译注:换句话说,到时候快乐的可是别人了,你在这干着急吧……)。
解决问题的关键就在这里。为了防止这一切的发生,Java编译器生成了相互配对的enter和exit指令。使用这种方法,一旦执行了进入synchronized的块或方法时,它必须传递一个相对应的MonitorExit给同一个对象。但是,一旦临界区域抛出异常,那么事情将变得非常糟糕。(译注:抛出异常后,程序会退出,monitorExit的字节码将不会被调用)。
public void hello() {
synchronized (this) {
System.out.println(&Hi!, I&#039;m alone here&);
让我们来分析下字节码:
aload_0 //将代码载入操作数堆栈
dup //再次载入
astore_1 //将此备份到保存在寄存器1的一个隐式变量中
monitorenter //从栈中出栈这个值来进入monitor
//真正的边界区域
getstatic Java/lang/System/out LJava/io/PrintS
ldc &Hi!, I&#039;m alone here&
invokevirtual Java/io/PrintStream/println(LJava/lang/S)V
aload_1 //获取寄存器1内的备份
monitorexit //出栈这个变量并退出monitor
goto 14 // 直接跳到最后并退出
// 编译器额外添加的catch声明,如果运行中出现异常,执行以下内容
aload_1 //获取寄存器1内的备份
monitorexit //退出monitor
athrow // 重新抛出异常类,将其载入操作数堆栈
从上面的代码分析中可以看出,编译器解决栈无法释放monitorExit的方法也非常直接:编译器会添加一个隐式的try catch声明来释放锁并抛出异常。
#真相3:另外一个问题是:在进入相应调用的enter之后、exit退出之前,被加锁的对象引用存放在什么地方。值得注意的是,多线程可能并行执行同一个同步块代码,但使用不同的锁对象。如果锁对象是一个方法反射后得到的结果,那么JVM几乎不大可能会再次执行它,因为这可能会改变对象的状态,甚至可能返回的不是同一个对象。当一个变量或者字段在monitor进入之后发生改变时,这种论断也是正确的。
Monitor变量。为了克服这个问题,编译器为方法添加了一个隐性的本地变量来保持锁对象的这个值。这是一种非常聪明的解决方案。相对于保存一个锁对象的引用,这中方法带来的损耗相对更低,因为没有使用并行堆结构来为线程获取锁对象的值(并发结构本身也可能需要加锁)。我第一次发现这个新变量是在构建Takip堆栈分析算法时,看到代码中pop了一个意料之外的变量。
我们应该意识到,所有的工作都是在Java编译器级别完成的。JVM非常乐意通过Monitor进入一个临界区段,但不退出(反之亦然);或者使用不同的对象进入相应的enter和exit的方法。
接下来我们进一步看看JVM级别,锁是如何实现的。在这一节中我们将查看hotspot SE 7的实现。由于锁机制对代码吞吐量有极大的影响,因此JVM做了非常多的优化使得获取锁和释放锁尽可能高效。
#真相4:JVM最强壮的机制之一就是线程的锁偏移(Locking Biasing)。锁是每个Java对象都拥有的本质属性,这就像每个对象都拥有hashcode或者他们类的引用一样。而且无论对象的类型,上述论断都是正确的(如果喜欢你甚至可以使用一个原始数组作为一个锁)。
这些数据存储在每个对象的头部(也称为类的标记)。有些放在对象头部的数据段是保留字段,专门用来存储对象的锁状态。这其中包含着表明对象锁状态的位字段(加锁/未加锁)以及当前拥有这个锁的线程:这个对象的偏移就指向这个线程。
为了给对象头部留出空间,Java线程对象位于VM堆比较低的位置,这样就可以压缩地址的大小,并且节省每个对象的头部的bit位(JVM32位的对应23bits,64位对应54bits)。
64位示意图
当JVM试着去获取一个对象的锁的时候,它将经历悲喜两重天。
#真相5:一旦一个线程成功把自己编程对象锁的拥有者,那么这个线程就成功地获得了锁。这取决与线程对象能否将锁对象头部字段的引用(一个内部Java线程对象的指针)指向自己。
获取锁。获取锁的第一步是使用一个CAS(compare-and-exchange比较并改变)指令。这一步通常非常的高效,因为他一般会被翻译成一个直接的CPU指令(比如cmpxchg)。CAS操作和操作系统特定线程的暂止程序一起为对象同步提供了基础的功能。
如果锁当前可用,或者之前已经对这个线程进行了偏移,那么线程可以立刻获取对象上的锁并且继续执行线程内的程序。如果CAS失败,JVM会执行一轮自旋锁定。这时线程暂止会将线程休眠,直到再次尝试CAS。如果这些尝试失败(意味着更高级别的锁争用),线程会把自己变为挂起状态,同时进入一个线程争用队列开始一系列的自旋锁定。
释放锁。当临界区通过MonitorExit退出时,拥有锁的线程将会尝试能否唤醒等待获取锁的挂起线程。这个过程也被称作选一个“继任者”。这能激活停滞的多个线程,同时也能防止出现——锁已经被释放但其他线程却仍处在暂止状态。
调试服务器多线程问题是非常苦逼、非常困难的,因为它们常常依赖非常极端、非常特殊的时间点以及操作系统算法。这也是当初我们为Takip工作的原因。
如果你有兴趣学习JVM锁是如何实现的,有代码和文档。
猛戳可以看到全方位的关于不同Java同步API和技术。
Scala并发请戳。
原文链接:
- 译文链接: [ 转载请保留原文出处、译者和译文链接。]
关于作者:
(新浪微博:)
可能感兴趣的文章
微信关注: ImportNew
分享Java相关的技术文章、工具资源和热点资讯。扫描加关注,碎片时间提高Java开发技能!
什么时候比C++快,这题目本身就输了。
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
&#8211; 写了文章?看干货?去头条!
&#8211; 为IT单身男女服务的征婚传播平台
&#8211; 优秀的工具资源导航
&#8211; 活跃 &#038; 专业的翻译小组
&#8211; 国内外的精选博客文章
&#8211; JavaScript, HTML5, CSS
&#8211; 专注Android技术分享
&#8211; 专注iOS技术分享
&#8211; 专注Java技术分享
&#8211; 专注Python技术分享
新浪微博:
微信号:importnew
反馈建议:@
广告与商务合作QQ:
& 2015 ImportNew当前访客身份:游客 [
当前位置:
oracle或者mysql数据库同步, &用自己服务器,能不能连接商场或者酒店的会员系统,
java代码怎么实现,SSH的例子怎么实现
共有4个答案
<span class="a_vote_num" id="a_vote_num_
主从复制,读写分离
<span class="a_vote_num" id="a_vote_num_
oracle 有工具的,golden gate
<span class="a_vote_num" id="a_vote_num_
mysql数据库同步不需要任何java代码,做成主从hot copy模式就可以了,主库的所有更改都会被实时到从库中
--- 共有 1 条评论 ---
oracle有没有类似mysql的主从hot copy模式
(11个月前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
实时同步很难做到吧
有什么技术问题吗?
开源jav...的其他问题
类似的话题

我要回帖

更多关于 java电影院售票系统 的文章

 

随机推荐