12月16日

在多线程环境中,多个线程可能会同时访问和修改共享资源,这可能导致数据不一致和竞态条件等问题。为了保证数据的正确性和一致性,需要对线程进行同步和互斥控制。

同步代码块:通过在代码块前加上synchronized关键字,可以将代码块标记为同步代码块。同步代码块需要指定一个锁对象,当线程进入同步代码块时,会尝试获取锁对象的锁,如果锁已被其他线程占用,则当前线程会进入阻塞状态,直到锁被释放。例如:
java
public class Counter {
private int count = 0;

public void increment() {
    synchronized (this) {  // 使用当前对象作为锁对象
        count++;
    }
}

public int getCount() {
    synchronized (this) {
        return count;
    }
}

}
同步方法:通过在方法前加上synchronized关键字,可以将整个方法标记为同步方法。同步方法的锁对象是当前对象(非静态同步方法)或类的Class对象(静态同步方法)。例如:
java
public class Counter {
private int count = 0;

public synchronized void increment() {  // 非静态同步方法
    count++;
}

public static synchronized void staticMethod() {  // 静态同步方法
    // ...
}

}
锁的概念:锁是一种用于控制多个线程对共享资源访问的机制。在Java中,每个对象都有一个与之关联的内部锁(也称为监视器锁或互斥锁),通过synchronized关键字可以获取和释放这个锁。锁的主要作用是确保同一时刻只有一个线程可以执行同步代码块或同步方法,从而避免了多线程并发访问共享资源时可能出现的数据不一致问题。
线程之间的通信是多线程编程中的一个重要方面,它允许线程之间传递信息、协调工作。Java提供了几种线程通信机制,如wait、notify和notifyAll方法,以及Condition接口等。

wait、notify和notifyAll方法:这些方法定义在Object类中,用于实现线程之间的等待和通知机制。wait方法使当前线程进入等待状态,并释放锁对象的锁,直到其他线程调用notify或notifyAll方法唤醒等待的线程。notify方法唤醒一个正在等待锁对象的线程,而notifyAll方法唤醒所有正在等待锁对象的线程。例如:
java
public class Buffer {
private boolean full = false;
private Object lock = new Object();

public void put() {
    synchronized (lock) {
        while (full) {
            try {
                lock.wait();  // 等待,释放锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 放入元素
        full = true;
        lock.notifyAll();  // 唤醒等待的线程
    }
}

public void get() {
    synchronized (lock) {
        while (!full) {
            try {
                lock.wait();  // 等待,释放锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 获取元素
        full = false;
        lock.notifyAll();  // 唤醒等待的线程
    }
}

}
Condition接口:Condition接口是Java并发包(java.util.concurrent)中提供的另一种线程通信机制,它比wait、notify和notifyAll方法更加灵活和强大。Condition接口与锁(Lock接口的实现类)配合使用,可以实现更复杂的线程通信场景。例如:
java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Buffer {
private boolean full = false;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();

public void put() {
    lock.lock();
    try {
        while (full) {
            notFull.await();  // 等待,释放锁
        }
        // 放入元素
        full = true;
        notEmpty.signalAll();  // 唤醒等待的线程
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

public void get() {
    lock.lock();
    try {
        while (!full) {
            notEmpty.await();  // 等待,释放锁
        }
        // 获取元素
        full = false;
        notFull.signalAll();  // 唤醒等待的线程
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

}

posted @   头发少的文不识  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示