线程安全方式一: 同步代码块
- 同步代码块关键字: synchronized(同步锁) {}
 - 将要同步的代码放在synchronized中
 - 任意一个对象充当同步锁 Runnble接口中可以考虑使用tihs充当同步锁
 - 多个线程必须使用统一个同步锁
 缺点: 代码效率慢 代码内容只能有一个线程执行 相当于单线程 ```java /**
- 创建人:LYY
 - 创建时间:2022/4/26
 同步代码块解决线程安全问题 */ public class SynchronizedTest {
public static void main(String[] args) { TicketOne ticketOne = new TicketOne(); // 创建线程一 Thread t1 = new Thread(ticketOne); t1.setName(“线程一:”); Thread t2 = new Thread(ticketOne); t2.setName(“线程二:”); Thread t3 = new Thread(ticketOne); t3.setName(“线程三:”); t3.setPriority(10); t2.start(); t1.start(); t3.start(); }
}
class TicketOne implements Runnable{
private int count = 100;Demo demo = new Demo();@Overridepublic void run() {while (true) {// 同步代码块synchronized(demo){// 2. 将要执行的操作 卸载run方法中if (count>0){System.out.println(Thread.currentThread().getName()+ "count = "+count);} else if (count == 0){break;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}count--;// 放弃当前线程权Thread.yield();}}}
}
```java/*** 创建人:LYY* 创建时间:2022/4/26* 模拟售票* 同100张车票 同时多个线程抢票* 每个线程执行一次 当前票数减一*/// 1. 实现Runnable接口public class Ticket implements Runnable{private int count = 100;@Overridepublic void run() {// 2. 将要执行的操作 卸载run方法中while (true) {// 同步锁synchronized(Ticket.class){if (count > 0) {System.out.println(Thread.currentThread().getName()+ "count = "+count);} else if (count == 0) {break;}count--;}}}}class TicketTest{@Testpublic void ticketTest() {// 3. 创建Runnable接口实现类的对象Ticket ticket = new Ticket();// 4. 将Runnable接口实现类的对象作为参数 传递给Thread对象 创建线程// 创建线程1Thread t1 = new Thread(ticket);t1.setName("线程一:");// 创建线程2Thread t2 = new Thread(ticket);t2.setName("线程二:");// 创建线程3Thread t3 = new Thread(ticket);t3.setName("线程三:");t3.start();t1.start();t2.start();}}
二、线程安全方式二:同步方法
- 创建一个方法 方法修饰符后添加synchronized关键字
 - 将要执行(同步)的操作写在synchronized方法中
 - run方法中调用synchronized方法
 - synchronized方法依然存在同步锁 该对象为隐式的
 - 继承Thread类中的同步方法需要声明为静态的 该同步方法同步锁隐式的 具体为class(.getClassz)
 实现Runnable接口中的同步方法只需要添加synchronized 该方法的同步锁为隐式的 具体为this ```java /**
- 创建人:LYY
 - 创建时间:2022/4/26
 使用同步方法解决继承Thread类的线程安全问题 */ public class ThreadTwo extends Thread{
private static int count = 100; static boolean isOk = true;
@Override public void run() { while (isOk) {
show();
} }
/**
- 同步方法 隐式的同步锁
 同步锁对象为class */ public static synchronized void show() {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + count);count--;
} else if (count == 0) {
isOk = false;
} } }
class ThreadTwoTest{ public static void main(String[] args) { ThreadTwo t1 = new ThreadTwo(); ThreadTwo t2 = new ThreadTwo(); ThreadTwo t3 = new ThreadTwo(); t3.setName(“线程三:”); t1.setName(“线程一:”); t2.setName(“线程二:”); t1.start(); t2.start(); t3.start(); } }
```java/*** 创建人:LYY* 创建时间:2022/4/26* 使用同步方法解决继承Thread类的线程安全问题*/public class ThreadTwo extends Thread{private static int count = 100;static boolean isOk = true;@Overridepublic void run() {while (isOk) {show();}}/*** 同步方法 隐式的同步锁* 同步锁对象为class*/public static synchronized void show() {if (count > 0) {System.out.println(Thread.currentThread().getName() + count);count--;} else if (count == 0) {isOk = false;}}}class ThreadTwoTest{public static void main(String[] args) {ThreadTwo t1 = new ThreadTwo();ThreadTwo t2 = new ThreadTwo();ThreadTwo t3 = new ThreadTwo();t3.setName("线程三:");t1.setName("线程一:");t2.setName("线程二:");t1.start();t2.start();t3.start();}}
三、Lock锁解决线程安全问题
- 实现线程接口(Runnable)或类(Thread)
 - 在线程类中创建Lock子类ReentrantLock对象
 - 在需要同步数据前 手动使用ReentrantLock对象调用锁(lock)方法
 - 同步数据操作接收 手动使用renntrantLock对象调用解锁(unlock)方法
```java
/**
- 创建人:LYY
 - 创建时间:2022/4/27
 - 使用同步锁解决线程安全问题
 - 同步锁使用ReentrantLock类
 - 在线程类中声明Lock的实现类对象 ReentrantLock
 
- 在需要同步的操作前 手动声明锁
 
- 在同步操作后 手动解锁 */ public class LockTest { }
 
 
class TicketTwo implements Runnable{
private int count = 100;// 同步锁ReentrantLock reentrantLock = new ReentrantLock(true);@Overridepublic void run() {while (true) {try {// 调用锁定方法reentrantLock.lock();if (count > 0) {System.out.println(Thread.currentThread().getName() + count);} else {break;}count--;} finally {// 调用解锁方法reentrantLock.unlock();}}}
}
```java/*** 创建人:LYY* 创建时间:2022/4/27*/public class Client implements Runnable{private int count;/*** 同步锁对象*/ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {for (int i = 0; i < 3; i++) {deposit();}}/**\* 存钱方法* 固定存款1000元*/public void deposit() {try {// 同步锁锁定lock.lock();count +=1000;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "存款成功! 余额:" + count);} finally {// 释放同步锁lock.unlock();}}}class ClientTest{public static void main(String[] args) {// 创建对象Client c = new Client();// 创建客户A(线程A)Thread thread1 = new Thread(c);Thread thread2 = new Thread(c);thread1.setName("线程A:");thread2.setName("线程B:");thread1.start();thread2.start();}}
