任意的对象都可以作为锁对象。凡是对象内部都维护了一个状态的,java同步机制就是使用了对象中的状态作为了锁的标识。 




需求: 模拟3个窗口同时在售50张 票 。


package com.cn.thread;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2016年7月3日21:54:52
* Desc:需求:模拟3个窗口同时在售50张票
*/
class Ticket extends Thread{
static int num = 50;//票数
static Object o = new Object();
public Ticket(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void run() {
while(true){
// synchronized("锁"){//√ 。。这个最简单的 锁。。。字符串常量池中,共享唯一
synchronized(o){//static修饰的对象,也是共享唯一的,都可以
if(num > 0){
System.out.println(Thread.currentThread().getName() + ":售出了第" + num + "号票" );
num--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println("票已经售完了");
break;
}
}
}
}
}
public class Demo4 {
public static void main(String[] args) {
Ticket ticket1 = new Ticket("售票员1");
Ticket ticket2 = new Ticket("售票员2");
Ticket ticket3= new Ticket("售票员3");
ticket1.start();
ticket2.start();
ticket3.start();
}
}


 


问题1 :为什么50张票被卖出了150次?





出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。


解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。

问题2: 出现了线程安全问题 ?


线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。

java线程同步机制的方式:


方式一:同步代码块


同步代码块的格式:

synchronized(锁对象){


需要被同步的代码...


同步代码块要注意事项:


1. 任意的一个对象都可以做为锁对象。


2. 在同步代码块中调用了sleep方法并不是释放锁对象的。


3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。


4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。


需求: 一个银行账户5000块,两夫妻一个拿着 存折,一个拿着卡,开始取钱比赛,每次只能取一千块,要求不准出现线程安全问题。


出现线程安全问题的根本原因:


1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。


2. 有多个语句操作了共享资源。

package com.cn.thread;
class GetMoney extends Thread{
static int allMoney = 5000;//银行总共的钱
public GetMoney(String name) {
super(name);
}
@Override
public void run() {
while(true){
synchronized("锁"){
if(allMoney > 0){
this.allMoney -= 1000;
System.out.println(this.currentThread().getName() + "取了" + 1000 + ",还剩" + allMoney);
}else{
System.out.println("钱取光了。。。");
break;
}
}
}
}
}
public class Demo5 {
public static void main(String[] args) {
GetMoney h = new GetMoney("丈夫");
h.start();
GetMoney w = new GetMoney("妻子");
w.start();
}
}