1.synchronized
本质:队列 锁
特点:java关键字 比较慢
public class synchronizedTest {
public static void main(String[] args) {
Data data = new Data();
for (int i = 0; i <30 ; i++) {
new Thread(()->{
data.sale();
},"A").start();
}
for (int i = 0; i <30 ; i++) {
new Thread(()->{
data.sale();
},"B").start();
}
}
}
class Data{
private int num=50;
public synchronized void sale(){ //传统方式
synchronized (this){ }
if (num>0){
System.out.println(Thread.currentThread().getName()+"卖票: "+num--);
}
}
}
2.锁
public interface java.util.concurrent.locks.Lock 所有已知实现类:ReentrantLock(可重入锁 常用) , ReentrantReadWriteLock.ReadLock , ReentrantReadWriteLock.WriteLock
Lock
实现提供比使用synchronized
方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition
。
随着这种增加的灵活性,额外的责任。 没有块结构化锁定会删除使用synchronized方法和语句发生的锁的自动释放。 在大多数情况下,应使用以下惯用语:
Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); }
ReentrantLock()
公平锁:可以先来后到
非公平锁 : 可以插队
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(()->{
for (int i = 0; i <30 ; i++) {
data.sale();
} },"A").start();
new Thread(()->{
for (int i = 0; i <30 ; i++) {
data.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i <30 ; i++) {
data.sale();
}
},"C").start();
}
}
class Data2{
private int num=50;
Lock lock=new ReentrantLock();
public void sale(){
lock.lock(); //加锁
try { // 业务代码
if (num>0){
System.out.println(Thread.currentThread().getName()+"卖票: "+num--);
}
}catch (Exception e){
}finally {
lock.unlock(); //解锁
}
}
}
synchronized和lock区别
1. synchronize 内置关键字 lock 一个java类
2.synchronize 无法判断锁的状态 lock 可以获取状态
3.synchronize 自动释放锁 lock 需要手动释放锁,死锁
4.synchronize 线程1(获得锁,等待)线程2(一直等待); lock:不一定会带等待下去
5.synchronize 可重入锁 不可以中断 非公平 lock:可重入锁 可以判断锁 非公平(可以设置)
6.synchronize 适合少量代码同步问题 lock适合大量同步代码块
可以尝试获取锁
生产者消费者问题 传统sync方式
import jdk.nashorn.internal.ir.CallNode;
public class ProductConsumer {
public static void main(String[] args) {
Data3 data3 = new Data3();
new Thread(()->{
for (int i = 0; i < 30; i++) {
try {
data3.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 30 ; i++) {
try {
data3.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 30; i++) {
try {
data3.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 30 ; i++) {
try {
data3.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
class Data3{
private int num=0;
public synchronized void increment() throws InterruptedException {
if (num!=0){ // 会出现负值 使用while 解决 // while (num==0){
//等待
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (num==0){ // while (num==0){
//等待
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
this.notifyAll();
}
}
//此处结果会出现 负值
产生了虚假唤醒问题 if 使用while代替
生产者消费者问题 JUC方式
Lock lock=new ReentrantLock();
Condition condition = lock.newCondition();
condition.await();
condition.signalAll();
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class newConditionTest {
public static void main(String[] args) {
Data4 data3 = new Data4();
new Thread(()->{
for (int i = 0; i < 30; i++) {
try {
data3.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 30 ; i++) {
try {
data3.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
class Data4{
private int num=0;
Lock lock=new ReentrantLock();
Condition condition = lock.newCondition();
public void increment() throws InterruptedException {
lock.lock();
try {
while (num!=0){
//等待
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (num==0){
//等待
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
不是有序的A-》B C-》D
指定唤醒相应线程
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class newConditionTest2 {
public static void main(String[] args) {
Data5 data5 = new Data5();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data5.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data5.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data5.printC();
}
},"C").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data5.printD();
}
},"D").start();
}
}
class Data5{
private int num=0;
Lock lock=new ReentrantLock();
Condition conditionA = lock.newCondition(); //指定唤醒相应线程
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition();
Condition conditionD = lock.newCondition();
public void printA(){
lock.lock();
try {
while (num!=0){
//等待
conditionA.await();
}
num++;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
conditionB.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (num==0){
//等待
conditionB.await();
}
num--;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
conditionC.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (num!=0){
//等待
conditionC.await();
}
num++;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
conditionD.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printD(){
lock.lock();
try {
while (num==0){
//等待
conditionD.await();
}
num--;
System.out.println(Thread.currentThread().getName()+">>"+num);
//通知其他线程
conditionA.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}