package com.day5.test;
/**
* User: Json
* Date: 2021/8/15
* 线程的同步
* 解决 多个线程执行的不确定性引起执行结果的不稳定
* 解决的问题点:
* 多个线程对数据共享时 会造成操作的不完整性 会破坏数据
* 比如有3000块钱
* 你和你女朋友同时取1000 就会出现线程安全问题
* 解决方式
* 方式一 同步代码块
* synchronized(同步监视器){
* //需要被同步的代码
* }
* 说明: 1.操作共享数据的代码 即为需要被同步的代码 -->synchronized 不能包代码多了 也不能包多了
* 2. 同步监视器 , 俗称: 锁 任何一个类的对象, 都可以充当锁
* 要求:多个线程必须要共用同一把锁
* 创建多线程有两种方式
* 第一种 是继承Thread 类实现
* 这一种 必须声明一个静态的对象属性 充当锁 如果不是 多线程就用的不是一把锁了
* 第二种 实现Runnable接口的方法 来实现
* 这一种 可以直接 声明普通的对象属性 来充当锁
* 这种 还可以使用 this 充当 对象 就不用声明 一个对象
* 一定要保证 锁 是唯一的 要么还会存在线程安全问题
* //把练习的 卖票程序 synchronized包起来
* 例: synchronized (obj){
* // synchronized (this){
* if(num>0){
*
* System.out.println(java.lang.Thread.currentThread().getName()+"卖票 票号为"+num);
* num--;
* }else{
* break;
* }
*
* }
* 方式二 同步方法
* 如果操作共享数据的代码完整的声明在一个方法中 我们就可以把这个方法声明成 同步方法 来解决 线程安全问题
* 例: 还是使用 练习题中的 卖票的程序 做例子
* // 把卖票的过程 提取出来给他声明成一个独立的方法 加上synchronized 关键字即可
* 如果是使用 继承Thread类来实现的多线程 也必须把这个方法声明成静态的 static
* 使用实现Runnable接口的方法 就不需要了
* private synchronized void show(){
* if(num>0){
*
* System.out.println(java.lang.Thread.currentThread().getName()+"卖票 票号为"+num);
* num--;
* }
* }
*
*
* 方式一 解决了线程安全问题
* 但是 在操作代码时 只有一个线程参与 其他线程等待 相当于是一个单线程执行的过程 效率低
**/
public class Synchronization {
}
package com.day6.test;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest implements Runnable{
private int num=100;
private ReentrantLock lock=new ReentrantLock(true);
@Override
public void run() {
while (true){
try {
lock.lock();
if(num>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖票:"+num);
num--;
}else{
break;
}
}finally {
lock.unlock();
}
}
}
}