//格式:
/*
* 同步代码块格式:锁对象可以是任意的但是必须要唯一
* synchronized(锁对象){
* 可能会出现线程安全的代码(访问了共享数据)
* }
* */
如下卖票案例所示;
Runnable实现类方法
public class RunnableImp implements Runnable {
//创建一个任意的锁对象
Object obj = new Object();
/*
* 同步代码块格式:锁对象可以是任意的但是必须要唯一
* synchronized(锁对象){
* 可能会出现线程安全的代码(访问了共享数据)
* }
* */
private int ticket = 100;
@Override
public void run() {
while (true){
synchronized (obj){ //传递任意的锁对象,对代码进行上锁,只有一个线程能访问
if (ticket > 0){
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}else {
return;
}
}
}
}
}
main方法:
public class Demo {
public static void main(String[] args) {
RunnableImp ri = new RunnableImp(); //创建实现类对象
Thread t0 = new Thread(ri); //将实现类对象传递给Thread方法
Thread t1 = new Thread(ri);
Thread t2 = new Thread(ri);
//开启3个线程
t0.start();
t1.start();
t2.start();
}
}
同步代码块使用了锁对象,这个对象也叫同步锁,也叫对象锁,也叫对象监视器
如上3个线程t0,t1,t2一起抢夺cpu的执行权,谁抢到了谁执行run方法进行卖票
假设t0抢到了执行权,执行run方法,遇到了synchronized代码块,这是t0会检查synchronized代码块是否有锁对象,发现有锁对象,进入到同步代码块中进行卖票
假设t1又抢到了cpu的执行权,执行run方法,遇到了synchronized代码块,这是t1会检查synchronized代码块是否有锁对象,发现没有锁对象,t1就会进入到阻塞状态,回一直带等待t0执行完同步代码块中的代码后,归还锁对象,t1获取到锁对象后才会进入到同步代码块中。
使用步骤:1.把访问共享数据的代码抽离出来,放到一个方法中,方法上添加synchronized修饰词
案例:
实现类:
public class RunnableImp implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true){
sellTicket();
}
}
private synchronized void sellTicket() { //同步方法
if (ticket > 0){
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}else {
return;
}
}
}
main的方法:
public class Demo {
public static void main(String[] args) {
RunnableImp ri = new RunnableImp();
Thread t0 = new Thread(ri);
Thread t1 = new Thread(ri);
Thread t2 = new Thread(ri);
//开启线程
t0.start();
t1.start();
t2.start();
}
}
实现类代码:
public class RunnableImp implements Runnable {
private static int ticket = 100;
@Override
public void run() {
while (true){
sellTicketStatic();
}
}
private static void sellTicketStatic() {
synchronized (RunnableImp.class){ //锁对象是本类的.class文件
if (ticket > 0){
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}else {
return;
}
}
}
}
main方法:
public class Demo {
public static void main(String[] args) {
RunnableImp ri = new RunnableImp();
Thread t0 = new Thread(ri);
Thread t1 = new Thread(ri);
Thread t2 = new Thread(ri);
//开启线程
t0.start();
t1.start();
t2.start();
}
}
使用步骤
/*
* 使用步骤:
* 1.在成员变量的位置创建一个ReentrantLock对象(这个对象是Lock接口的子类对象)、
* 2.在可能出现安全问题的代码前调用Lock接口的方法lock获取锁
* 3.在可能出现安全问题的代码后调用Lock接口的方法unlock获取锁
* */
实现类代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class RunnableImp implements Runnable {
private int ticket = 100;
//1.在成员变量的位置创建一个ReentrantLock对象(这个对象是Lock接口的子类对象)、
Lock l = new ReentrantLock();
@Override
public void run() {
while (true){
//2.在可能出现安全问题的代码前调用Lock接口的方法lock获取锁
l.lock(); //获取锁
if (ticket > 0){
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
}else {
return;
}
//3.在可能出现安全问题的代码后调用Lock接口的方法unlock获取锁
l.unlock(); //释放锁
}
}
}
main方法代码:
public class Demo {
public static void main(String[] args) {
RunnableImp ri = new RunnableImp();
Thread t0 = new Thread(ri);
Thread t1 = new Thread(ri);
Thread t2 = new Thread(ri);
//开启线程
t0.start();
t1.start();
t2.start();
}
}