0
点赞
收藏
分享

微信扫一扫

kafka集群与redis集群的概念对应关系

诗与泡面 2023-11-16 阅读 41

 


 

文章目录

一.🔐线程安全

1.1🔓案例引入

1.1.1🔑问题

1.1.2🔑实例操作

1.2🔓说明

二.🔐同步代码块

2.1🔓语法格式

2.2🔓全局锁

🚩实例练习1

2.3🔓任意锁

🚩实例练习2

2.4🔓局部锁

🚩实例练习3

2.5🔓this对象作为锁

🚩实例练习4

2.6🔓注意

三.🔐同步方法

3.1🔓语法格式

3.2🔓实例练习

3.3🔓思考

四.🔐同步锁(重入锁)

4.1🔓语法格式

4.2🔓实例练习


一.🔐线程安全

1.1🔓案例引入

1.1.1🔑问题

       电影院上映一部电影,共有三个窗口,请你设计一个模拟电影院卖票的程序。

1.1.2🔑实例操作

代码如下👇🏻 

package Process3;

public class SellTicket implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号

@Override
public void run() {
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++
}
}
}

package Process3;

public class SellTicketDemo {
public static void main(String[] args) {
// 创建资源对象
SellTicket st = new SellTicket();

// 创建三个线程对象
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");

// 启动线程
t1.start();
t2.start();
t3.start();
}
}

运行结果👇🏻

总结:该方法不可以,有重票和漏票和多票问题。 

1.2🔓说明

           线程安全问题其实就是由多个线程同时处理共享资源所导致的。要想解决线程安全问题,必须得保证处理共享资源的代码在任意时刻只能有一个线程访问。为此,Java中提供了线程同步机制。

二.🔐同步代码块

2.1🔓语法格式

原理

      (1).当线程执行同步代码块时,首先会检查lock锁对象的标志位。

      (2).默认情况下标志位为1,此时线程会执行Synchronized同步代码块,同时将锁对象的标志位置为0。

      (3).当一个新的线程执行到这段同步代码块时,由于锁对象的标志位为0,新线程会发生阻塞,等待当前线程执行完同步代码块后。

      (4).锁对象的标志位被置为1,新线程才能进入同步代码块执行其中的代码,这样循环往复,直到共享资源被处理完为止。

2.2🔓全局锁

🚩实例练习1

代码如下👇🏻 

package Sell;

public class SellTicket implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号
Object o =new Object();//全局锁

@Override
public void run() {
while (tickets>0) {
synchronized (o) {
if(tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++
}
}

}
}
}

package Sell;


public class SellTicketDemo1 {
public static void main(String[] args) {
// 创建资源对象
SellTicket1 st = new SellTicket1();

// 创建三个线程对象
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");

// 启动线程
t1.start();
t2.start();
t3.start();
}
}

运行结果👇🏻

2.3🔓任意锁

🚩实例练习2

代码如下👇🏻 

package Sell;

public class SellTicket1 implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号
Demo lock =new Demo();//任意锁

@Override
public void run() {
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
// 为什么有if判断?
// 如果没有if,t1执行结束,tickets=0,这样t2,t3再执行同步代码块之后,票会变成负数,票会多卖
if(tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++ // 多卖21,22
}
}

}
}
}
class Demo{
//任意类
}

运行结果👇🏻

2.4🔓局部锁

🚩实例练习3

代码如下👇🏻 

package Sell;

public class SellTicket1 implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号

@Override
public void run() {
Object lock =new Object();//局部锁锁不住
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
// 为什么有if判断?
// 如果没有if,t1执行结束,tickets=0,这样t2,t3再执行同步代码块之后,票会变成负数,票会多卖
if(tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++ // 多卖21,22
}
}

}
}
}

运行结果👇🏻

总结:该方法不可以,有重票和漏票问题。

2.5🔓this对象作为锁

🚩实例练习4

代码如下👇🏻 

package Sell;

public class SellTicket1 implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号

@Override
public void run() {
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
// 为什么有if判断?
// 如果没有if,t1执行结束,tickets=0,这样t2,t3再执行同步代码块之后,票会变成负数,票会多卖
if(tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++ // 多卖21,22
}
}

}
}
}

运行结果👇🏻

说明:项目开发中一般使用this关键字作为锁对象。

2.6🔓注意

三.🔐同步方法

3.1🔓语法格式

3.2🔓实例练习

 代码如下👇🏻 

package Sell;

public class SellTicket1 implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号

@Override
public void run() {
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}

Selltickets ();

}
}
//方法抽取:
//同步方法
public synchronized void Selltickets () {
if(tickets>0) {

System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++ // 多卖21,22
}
}
}

package Sell;


public class SellTicketDemo1 {
public static void main(String[] args) {
// 创建资源对象
SellTicket1 st = new SellTicket1();

// 创建三个线程对象
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");

// 启动线程
t1.start();
t2.start();
t3.start();
}
}

运行结果👇🏻

3.3🔓思考

     (1).同步方法的格式及锁对象问题?

           把同步关键字加在方法上

     (2).同步代码块的锁对象是谁?

           任意全局对象   一般使用this作为锁对象

     (3).同步方法的锁是谁?

           this,它是隐含的

四.🔐同步锁(重入锁)

4.1🔓语法格式

4.2🔓实例练习

代码如下👇🏻 

package Sell;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket1 implements Runnable {

private int tickets = 20;//总票数
private int ticketId = 1;//票号
Lock lock =new ReentrantLock();//同步锁(重入锁)

@Override
public void run() {
while (tickets>0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();//上锁
if(tickets>0) {

System.out.println(Thread.currentThread().getName() + "正在出售第"+ ticketId + "张票");
tickets--; //剩余票数--
ticketId++; //票号++
}
lock.unlock();//开锁
}
}
}
package Sell;


public class SellTicketDemo1 {
public static void main(String[] args) {
// 创建资源对象
SellTicket1 st = new SellTicket1();

// 创建三个线程对象
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");

// 启动线程
t1.start();
t2.start();
t3.start();
}
}

运行结果👇🏻


举报

相关推荐

0 条评论