当不做任何处理的时候会出现线程不安全的情况,加入三个线程一个任务卖十张票代码如下:
package ceshi;
/**
* 线程安全使用排对机制 synchronized 同步锁
*/
public class Demo4 {
public static void main(String[] args) {
//多态的形式创建
Runnable runnable = new MyThread();
//三个线程进行卖票
new Thread(runnable).start();
new Thread(runnable).start();
new Thread(runnable).start();
}
static public class MyThread implements Runnable{
//假设有十张票
private int num = 10;
@Override
public void run() {
while (true){
//如果票数大于0则可以卖
if (num>0){
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName()+"出票成功!还剩"+num);
}else {
break;
}
}
}
}
}
就会出现以下这种情况
Thread-1出票成功!还剩-1
Thread-2出票成功!还剩-2
Thread-0出票成功!还剩-1
这就是线程不安全导致的,
现在我们对其进行同步使用synchronized就会排队进行卖票。
static public class MyThread implements Runnable{
//假设有十张票
private int num = 10;
//同步锁
private Object o = new Object();
@Override
public void run() {
while (true){
//如果票数大于0则可以卖
synchronized (o){
if (num>0){
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName()+"出票成功!还剩"+num);
}else {
break;
}
}
}
}
}
这样即可解决线程不安全问题,值得注意的是上锁的位置不可以如下图这样
public void run() {
Object o = new Object();
while (true){
//如果票数大于0则可以卖
synchronized (o){
if (num>0){
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName()+"出票成功!还剩"+num);
}else {
break;
}
}
}
}
或者下图:
public void run() {
while (true){
//如果票数大于0则可以卖
Object o = new Object();
synchronized (o){
if (num>0){
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName()+"出票成功!还剩"+num);
}else {
break;
}
}
}
}
这样相当于是锁在自己身上,并没有做到同步锁的要求,那么还是存在线程不安全的问题。
2.同步方法
如果不是静态的,synchronized的锁是this
如果是静态的,synchronized的锁是该类.class。
那么同步方法的实现代码如下:
主方法内容不变,实现接口的类里面将while判断的内容写成一个方法然后加上synchronized即可
static public class MyThread implements Runnable{
//假设有十张票
private int num = 10;
### 最后
**给读者们一个小福利,有需要这些资料的朋友们[可以点击我,即可免费](https://codechina.csdn.net/m0_60958482/java-p7)领取资料!**
### ActiveMQ消息中间件面试专题
* 什么是ActiveMQ?
* ActiveMQ服务器宕机怎么办?
* 丢消息怎么办?
* 持久化消息非常慢怎么办?
* 消息的不均匀消费怎么办?
* 死信队列怎么办?
* ActiveMQ中的消息重发时间间隔和重发次数吗?
**ActiveMQ消息中间件面试专题解析拓展:**
![BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM](https://img-blog.csdnimg.cn/img_convert/8efa9a2953ecb956b70cefd577a9129c.png)
* * *
# redis面试专题及答案
* 支持一致性哈希的客户端有哪些?
* Redis与其他key-value存储有什么不同?
* Redis的内存占用情况怎么样?
* 都有哪些办法可以降低Redis的内存使用情况呢?
* 查看Redis使用情况及状态信息用什么命令?
* Redis的内存用完了会发生什么?
* Redis是单线程的,如何提高多核CPU的利用率?
![BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM](https://img-blog.csdnimg.cn/img_convert/b45eb8f2023a61c83f1e1c3143f1ba5a.png)
* * *
# **Spring面试专题及答案**
* 谈谈你对 Spring 的理解
* Spring 有哪些优点?
* Spring 中的设计模式
* 怎样开启注解装配以及常用注解
* 简单介绍下 Spring bean 的生命周期
**Spring面试答案解析拓展**
![BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM](https://img-blog.csdnimg.cn/img_convert/cb59884f4c4079976be33cc3bb2bcd67.png)
* * *
# 高并发多线程面试专题
* 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
* Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
* Java 中 wait 和 sleep 方法有什么区别?
* 如何在 Java 中实现一个阻塞队列?
* 如何在 Java 中编写代码解决生产者消费者问题?
* 写一段死锁代码。你在 Java 中如何解决死锁?
**高并发多线程面试解析与拓展**
![BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM](https://img-blog.csdnimg.cn/img_convert/be8acb44f45db0641d658317959d642c.png)
* * *
# jvm面试专题与解析
* JVM 由哪些部分组成?
* JVM 内存划分?
* Java 的内存模型?
* 引用的分类?
* GC什么时候开始?
**JVM面试专题解析与拓展!**
![BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM](https://img-blog.csdnimg.cn/img_convert/3f8cee2db0c7431645e37921121b2ea9.png)
实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
* Java 中 wait 和 sleep 方法有什么区别?
* 如何在 Java 中实现一个阻塞队列?
* 如何在 Java 中编写代码解决生产者消费者问题?
* 写一段死锁代码。你在 Java 中如何解决死锁?
**高并发多线程面试解析与拓展**
[外链图片转存中...(img-HG3S3PYc-1630136089095)]
* * *
# jvm面试专题与解析
* JVM 由哪些部分组成?
* JVM 内存划分?
* Java 的内存模型?
* 引用的分类?
* GC什么时候开始?
**JVM面试专题解析与拓展!**
[外链图片转存中...(img-DiWl4AFo-1630136089096)]