/*
* 举例:卖票
* 假设,有10张票,分三个窗口同时卖
*
* 1、线程安全问题:
* 当多个线程使用“共享数据”时,就会有线程安全问题。
* 当一个线程修改了“共享数据”,是会影响其他线程。
*
* 2、如何解决?
* 加锁
*
* 形式一:同步代码块
* 形式二:同步方法
*
* 3、同步代码块
* 语法格式:
* synchronized(锁对象){
* 需要加锁的代码
* }
*
* 锁对象,又称为监视器对象,同一时刻,某一段代码,只允许一个线程运行,这个锁就记录谁现在在运行,其他线程进不来。
*
* 锁对象的选择:
* (1)可以是任意类型的对象
* (2)必须是这几天线程要使用同一个锁对象
*
* 锁的代码的范围的选择:
* (1)太大了:不行
* (2)太小了:不行
* 锁一次任务
*/
public class Test09 {
public static void main(String[] args) {
Ticket t1 = new Ticket("窗口一");
Ticket t2 = new Ticket("窗口二");
Ticket t3 = new Ticket("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class Ticket extends Thread{
private static int total = 1000;
private static Object lock = new Object();//锁的选择之一,单独造一个锁对象
public Ticket(String name) {
super(name);
}
public void run(){
// synchronized (this) {//这里使用this不行,因为这个this,对于三个线程来说不是同一个
while(true){
synchronized (lock) {
if(total > 0){
System.out.println(getName() + "卖出一张票");
total--;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("剩余:" + total);
}else{
break;
}
}
}
}
}
/*
* 步骤:
* (1)编写线程类,实现Runnable
* (2)重写run
* (3)创建线程对象
* (4)启动线程
*/
public class Test10 {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t,"窗口一");
Thread t2 = new Thread(t,"窗口二");
Thread t3 = new Thread(t,"窗口三");
t1.start();
t2.start();
t3.start();
}
}
class Ticket implements Runnable{
private int total = 10;
@Override
public void run() {
while(true){
synchronized (this) {//选择this当锁,可以,因为只有一个Ticket的对象
if(total>0){
System.out.println(Thread.currentThread().getName() +"卖出一张票");
total--;
System.out.println("剩余:" + total);
}else{
break;
}
}
}
}
/*
* 同步方法的语法格式:
* 【修饰符】 synchronized 返回值类型 方法名(【形参列表】)throws 异常列表{
* }
*
* synchronized 【修饰符】 返回值类型 方法名(【形参列表】)throws 异常列表{
* }
*
* 同步方法的锁对象,程序员无法选择:
* (1)非静态方法:this
* (2)静态方法:当前类的Class对象
*/
public class Test11 {
public static void main(String[] args) {
Ticket t1 = new Ticket("窗口一");
Ticket t2 = new Ticket("窗口二");
Ticket t3 = new Ticket("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class Ticket extends Thread{
private static int total = 10;
public Ticket(String name) {
super(name);
}
public void run(){
while(total>0){//程序停止的条件
saleOneTicket();
}
}
public synchronized static void saleOneTicket(){
if(total > 0){//线程安全问题的条件
System.out.println(Thread.currentThread().getName() + "卖出一张票");
total--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("剩余:" + total);
}
}
//同步方法,锁的是方法的一次调用过程
//非静态方法的锁对象是this,这里使用this,不是合格的锁对象
/*public synchronized void saleOneTicket(){
if(total > 0){//线程安全问题的条件
System.out.println(getName() + "卖出一张票");
total--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("剩余:" + total);
}
}*/
}
public class Test12 {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t,"窗口一");
Thread t2 = new Thread(t,"窗口二");
Thread t3 = new Thread(t,"窗口三");
t1.start();
t2.start();
t3.start();
}
}
class Ticket implements Runnable{
private int total = 10;
@Override
public void run() {
while(total>0){
saleOneTicket();
}
}
//当前同步方法的锁对象是this,可以的,因为只有一个Ticket
public synchronized void saleOneTicket(){
if(total>0){
System.out.println(Thread.currentThread().getName() +"卖出一张票");
total--;
System.out.println("剩余:" + total);
}
}
}
死锁问题:
/*
* 死锁:
* 两个线程,互相持有,占有对方想要的锁,不放手。
*/
public class TestDeadLock {
public static void main(String[] args) {
Object g = new Object();
Object m = new Object();
Boy b = new Boy(g,m);
Bang bang = new Bang(g,m);
b.start();
bang.start();
}
}
//男朋友
class Boy extends Thread{
private Object girl;
private Object money;
public Boy(Object girl, Object money) {
super();
this.girl = girl;
this.money = money;
}
public void run(){
synchronized (money) {
System.out.println("你放了我女朋友,我给你500万");
synchronized (girl) {
System.out.println("给了对方500万");
}
}
}
}
//绑匪
class Bang extends Thread{
private Object girl;
private Object money;
public Bang(Object girl, Object money) {
super();
this.girl = girl;
this.money = money;
}
public void run(){
synchronized (girl) {
System.out.println("你给我500万,我放了你女朋友");
synchronized (money) {
System.out.println("放人");
}
}
}
}