322静态同步方法和323解决线程安全问题_lock锁
静态同步方法
public class SynchronizedStatic implements Runnable {
static boolean staticFlag = true;
public static synchronized void test0(){
for(int i=0;i<5;i++){
System.out.println("test0:"+Thread.currentThread().getName() + " "+ i);
}
}
public void test1(){
synchronized (this) {
// synchronized (SynchronizedStatic.class) {
for(int i=0;i<5;i++){
System.out.println("test1:"+Thread.currentThread().getName() + " "+ i);
}
}
}
public void run() {
if(staticFlag){
staticFlag = false;
test0();
}else{
staticFlag = true;
test1();
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedStatic ss = new SynchronizedStatic();
new Thread(ss).start();
//保证第一条线程开始运行
// Thread.sleep(1);
new Thread(ss).start();
}
}
解决线程安全问题的一种方案:使用同步代码块格式:synchronized(锁对象){可能会出现线程安全问题的代码(访问了共享数据的代码)}注意:1.通过代码块中的锁对象,可以使用任意的对象2.但是必须保证多个线程使用的锁对象是同一个3.锁对象作用:把同步代码块锁住,只让一个线程在同步代码块中执行
解决线程安全问题_lock锁
解决线程安全问题-Lock锁
java.util.concurrent.locks.Lock`机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,
同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock():加同步锁。
public void unlock():释放同步锁。
解决线程安全问题的三种方案:使用Lock锁java.util.concurrent.locks.Lock接口
Lock实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作。
lock接口中的方法:
void lock()获取锁。
void unLock()释放锁。
java.util.concurrent.Locks.ReentrantLock impLements Lock接口
使用步骤:
1.在成员位置创建一个Reentrantlock对象l
2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁
public class RunnableImpl implements Runnable{
Lock l = new ReentrantLock();
private int ticket = 100;
//设置线程任务:卖票
@Override
public void run() {
//使用死循环,让卖票操作重复执行while(true){
//先判断票是否存在
while (true){
l.lock();
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,卖票ticket--
System.out .println(Thread.currentThread( ).getName()+"-->正在卖第" +ticket+"张票"+ticket--);
}
l.unlock();
}
}
}
public class RunnableImpl implements Runnable{
Lock l = new ReentrantLock();
private int ticket = 100;
//设置线程任务:卖票
@Override
public void run() {
//使用死循环,让卖票操作重复执行while(true){
//先判断票是否存在
while (true){
l.lock();
if(ticket>0){
try {
Thread.sleep(10);
//票存在,卖票ticket--
System.out .println(Thread.currentThread( ).getName()+"-->正在卖第" +ticket+"张票"+ticket--);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
l.unlock();
}
}
}
}
}
public static void main(String[] args) {
RunnableImpl runnable = new RunnableImpl();
Thread thread = new Thread(runnable);
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread.start();
thread1.start();
thread2.start();
}
--
package cn.itcast.day12.demo09;
/**
* @author admin
* @version 1.0.0
* @ClassName RunnableImpl.java
* @Description TODO
* @createTime 2021年09月28日 18:47:00
*/
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 卖票案例出现了线程安全问题
* 卖出了不存在的票和重复的票
*
* 解决线程安全问题的三种方案:使用lock锁
* java.util.concurrent.locks.Lock接口
*
* Lock实现提供了比使用synchronized方法和语句获得更广泛的锁定操作
* Lock接口中的方法
* void Lock()获取锁
* void unlock() 释放锁
* java.util.concurrent.Locks.ReentrantLock implements Lock接口
*
* 使用步骤
* 1.在成员位置创建一个ReentrantLock对象
* 2.在有可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
* 3.有可能会出现安全问题的代码后调用Lock接口中的方法unlock关闭所
*
*
*
*/
public class RunnableImpl implements Runnable {
// 定义一个多线程共享资源
private int ticket = 100;
// 1.在成员位置创建一个ReentrantLock对象
Lock l = new ReentrantLock();
// 设置线程任务 卖票
@Override
public void run() {
// 使用死循环 让卖票操作重复操作
while (true) {
// 2.在有可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
l.lock();
// 先判断票是否存在
if (ticket > 0) {
// 提高安全问题出现的概率,让程序睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
ticket--;
}
l.unlock();
}
}
}
package cn.itcast.day12.demo09;
/**
* @author admin
* @version 1.0.0
* @ClassName Demo01Ticket.java
* @Description TODO
* @createTime 2021年09月28日 14:23:00
*/
/**
* 模拟卖票案例
* 创建3个线程,同时开启,对共享的票进行出售
*
*/
public class Demo01Ticket {
public static void main(String[] args) {
// 创建Runnable接口的实现类
Runnable run = new RunnableImpl();
// 创建Thread类对象 构造方法中传递Runnable接口的实现类对象
Thread t = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
// 调用start方法开启多线程
t.start();
t1.start();
t2.start();
}
}