Directorio de artículos
Cerrar con llave
Veamos un ejemplo simple de venta de boletos (sin candado):
package demo1;
public class SaleTicketTest {
public static void main(String[] args) {
// lambda 表达式 ()表示run() 其中"()"中可以写明参数 ,->{} 表示 run后的代码块{}
// 支持 lambda 表达式,必须是接口上有 @FunctionalInterface 注解
// @FunctionalInterface 注解的接口,只能存在一个 抽象方法!
Ticket ticket = new Ticket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"C").start();
}
}
class Ticket{
private Integer num = 40;
public void sale(){
if(num > 0){
num --;
System.out.println(Thread.currentThread().getName()+"卖票,剩余:"+num+"张");
}
}
}
Ejecute unas cuantas veces más y la información de registro obtenida es la siguiente:
¡El orden está desordenado!
JDK 1.5之前的做法:
¡Tómelo
synchronized
para bloquearlo!
class Ticket{
private Integer num = 40;
public synchronized void sale(){
if(num > 0){
num --;
System.out.println(Thread.currentThread().getName()+"卖票,剩余:"+num+"张");
}
}
}
JDK 1.5 之后的做法:
Puede utilizar java.util.concurrent.locks.Lock
clases para implementar 加锁
y 释放锁
operar.
package demo1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SaleTicketTest3 {
public static void main(String[] args) {
// lambda 表达式 ()表示run() 其中"()"中可以写明参数 ,->{} 表示 run后的代码块{}
// 支持 lambda 表达式,必须是接口上有 @FunctionalInterface 注解
// @FunctionalInterface 注解的接口,只能存在一个 抽象方法!
Ticket3 ticket3 = new Ticket3();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket3.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket3.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket3.sale();
}
},"C").start();
}
}
class Ticket3{
private Integer num = 40;//目标数
private Integer saleNum = 0; //卖出数
// 可重入锁(最实用)
// 调用无参构造,生成 “不公平锁”
// 可以传递参数 ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();} true为公平锁
// 不公平锁,性能更好,可以插队!
Lock lock = new ReentrantLock();
public void sale(){
lock.lock(); //加锁
//lock.tryLock();
try {
if(num > 0){
num --;
saleNum ++;
System.out.println(Thread.currentThread().getName()+"卖票,共卖了"+saleNum+"张,剩余:"+num+"张");
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();//释放锁
}
}
}
La diferencia entre sincronizado y bloqueo
- Synchronized es una palabra clave de Java, y Lock es solo una clase en Java.
- Sincronizado no puede percibir el estado del bloqueo, pero Lock puede determinar si el bloqueo se obtiene con éxito.
- Bloqueos y liberaciones sincronizados automáticamente, pero el bloqueo debe ser manual.
- Si el hilo sincronizado está bloqueado, otros hilos seguirán esperando, pero es posible que Lock no espere (lock.tryLock ()).
- sincronizados pueden ser cerraduras reentrantes, ininterrumpidas, injustas; las
cerraduras pueden ser cerraduras reentrantes, puede juzgar si interrumpir, puede elegir cerradura justa / cerradura injusta. - sincronizado es adecuado para una pequeña cantidad de problemas de sincronización de código; Lock es adecuado para una gran cantidad de códigos sincronizados.