Java中的不同锁

PADS Layout中快速导入自定义元器件封装的实用技巧 本文详细介绍了在PADS Layout中高效导入自定义元器件封装的实用技巧。针对封装“找不到”、“对不上”、“导不进”三大痛点,系统梳理了从封装文件来源识别、库规划管理,到三种核心导入场景(从库文件添加、从其他设计借用、处理第三方格式)的完整操作流程,并提供了导入后的关键验证清单与常见问题排查方法,旨在帮助硬件工程师快速掌握这一提升设计效率的关键技能。 阅读详情

一 概述 

锁可以理解成一种用于控制对共享资源访问的工具,它在在Java5之前,在协调对共享对象的访问可以使用的内置锁机制是借助关键字synchronized和volatile实现,Java5之后增加了Lock接口,并提供了相应是实现类,如ReentrantLock类等。它是弥补内置加锁机制不适合时的一种高级功能。

二 Lock接口

Lock接口定义了一组抽象的加锁操作。与内置加锁机制不同的是,Lock提供了一种无条件,可轮询,定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显示的,故可以称这些锁为显式锁。在Lock的实现中必须提供与内部锁相同的内存可见性语义,但在加锁语义,调度算法,顺序保证以及性能等方面有所不同。

public interface Lock {
    //获取锁,如果锁被其他线程获取了就会进入等待状态
    void lock();
    //中断锁
    void lockInterruptibly() throws InterruptedException;
    //获取锁
    boolean tryLock();
    //尝试在time时间范围内获取锁,如未获取则会返回false
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    //释放锁
    void unlock();
    //条件
    Condition newCondition();
}

Lock接口的实现步骤

* Lock lock = ...;
* if (lock.tryLock()) {
*   try {
*     // manipulate protected state
*   } finally {
*     lock.unlock();//必须在finally中做释放锁操作
*   }
* } else {
*   // perform alternative actions
* }}

为什么需要Lock,synchronized关键字为什么不够用

synchronized关键字定义的内置锁的释放情况少,试图获取锁是不能设置超时,不能中断一个正在试图获得锁的线程。只有synchronized锁定的代码全部执行完后锁才会被释放,或者是执行过程中发生异常后,JVM会自动将该锁释放。

如果某个线程任务执行到一半的时候需要释放锁时,synchronized关键字是无法满足要求。

如果某线程想在一定时间段内尝试获取某锁,如果获取到锁就会进行任务执行,否则返回false,synchronized关键字也是无法满足要求的。

此外,通过synchronized关键字是无法判断当前尝试获取锁的线程是否真正获取到锁。

基于synchronized关键字这些不足,Lock的出现能够很好的解决这些问题。

值得注意的是Lock无法像synchronized一样在异常时自动释放锁,需要在finally代码块中主动使用unlock()方法进行锁的释放,以保证锁在发生异常时一定会被释放。

当然如果线程任务中出现死循环的时候,synchronized设置的内部锁会出现死锁现象。

二 锁的可见性

一般情况下某一线程是无法实时查看另一线程中数据的动态。由于happens-before原则的存在,在当某一线程中的数据发生修改完成后,其他线程一定能够发现同一数据的变化,则其他线程也一定存在happens-before原则。

Lock加锁和synchronized声明的内部锁有同样的内存语义,所以下一个线程加锁后可以看到前一个线程解锁前发生的所有操作,即存在happens_before原则。

对于某一线程需要获取synchronized关键字定义的锁时,需要其他线程先释放当前锁,而且synchronized关键字在释放锁之前会将自己对数据的修改写回内存中。

三 锁的分类

锁的分类并不是互斥的,可以多个类型并存,即一个锁可能属于多个类型的锁。如ReentrantLock既是互斥锁,又是可重入锁。

三 乐观锁和悲观锁

乐观锁也称作非互斥同步锁,悲观锁称为互斥同步锁。

悲观锁(互斥同步锁)

互斥同步锁存在线程的阻塞和唤醒所以会带来性能问题,因为悲观锁为线程独占的,其他线程想要获取相同资源时就需要进行等待。

存在永久阻塞问题:如果持有锁的线程出现死循环,死锁等活跃性问题,那么等待线程释放锁的线程将处于永久等待状态,将永远得不到执行。

优先级反转:如果获取锁的线程优先级比较低而等待锁的线程优先级比较高,则会出现线程优先级的反转。

Java中的悲观锁的实现为synchronized关键字修饰和Lock相关类的实现。

乐观锁(非互斥同步锁)

允许多个线程同时获取锁,当某一线程获取的数据同起初获取的数据不同,说明其他人在这段时间内修改过数据,所以不能继续刚才的更新数据过程,我会选择放弃,报错,重试等策略。

乐观锁的实现一般都是利用CAS算法实现,即获取锁的线程可以在一个原子操作内完成数据的改变,所以其他线程是无法影响到当前线程的对数据的修改。这种实现在java中的原子类和并发容器中都有使用。

Git是乐观锁实现的典型例子,当我们往远端仓库push的时候,git会检查远端仓库的版本是否与本地库版本一致,如果一致我们可以顺利的提交代码到远程仓库,并产生要给新的版本号。如果不一致,说明在此期间存在以他的代码提交,所以无法进行本次代码的提交。

数据库的select for update就是悲观锁,我们通过version控制数据库就是通过乐观锁实现,在表中添加一个字段lock_version在我们先查询该更新语句的版本version,select versionOne from table;然后update table set version = version+1 where version = versionOne;这种操作类似于CAS操作,实现了乐观锁。

悲观锁与乐观锁的比较

悲观锁的起始开销要比乐观锁高,但是某一线程获取悲观锁之后就会一直持有锁,临界区持锁时间就算越来越差,也不会对互斥锁的开销造成影响。

悲观锁适合并发写入较多的情况,使用于临界区持有锁时间比较长的情况,悲观锁可以避免当量的无用自旋消耗。如临界区存在IO操作,临界区代码复杂或者循环量大,临界区资源竞争激烈。

乐观锁的起始开销要比悲观锁低,但是可能存在很长时间的自旋和不停的重试,那么消耗的资源也会越来越多。

乐观锁适合并发写入少,大部分为度读操作的场景,不加锁的能让读取性能提高。

四 可重入锁和非可重入

可重入理解:可以理解为在北京买车上牌照,需要摇号,如果我摇到号就相当于我获取锁。当我需要为第二辆车进行摇号上牌照时候,被通知为我已经拥有一个牌照不能在参加摇号,除非放弃之前的牌照,这种情况为非重入。而我可以为第二辆车摇号的同时无需放弃之间拥有的牌照的情况表示为可重入。

Synchronized,ReentrantLock均为可重入锁,重入锁也是一种递归锁。重入锁的存在可以避免死锁,同时提高了封装性,减少加锁时必须释放锁的操作。

ReentrantLock方法

    //查看锁是否被当前线程所持有
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    protected final boolean isHeldExclusively() {
        return getExclusiveOwnerThread() == Thread.currentThread();
    }

    //查看这把锁的等待队列有多长
    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    public final int getQueueLength() {
        int n = 0;
        for (Node p = tail; p != null; p = p.prev) {
            if (p.thread != null)
                ++n;
        }
        return n;
    }

可重入锁源码

       final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //获取锁时先判断,如果当前线程为已经占有锁的线程,则state值加1并返回true.
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
        //释放锁时也是先判断当前线程是否时已占有锁的线程,然后判断state是否为0,如果是则释放锁
        protected final boolean tryRelease(int releases) {
            //c表示当前线程重入的次数
            int c = getState() - releases;
            //判断当前线程是持有锁的线程,如果不是持有锁的线程就会抛出异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            //当可重入的次数大于0的时候,free会一直为false
            boolean free = false;
            //当前c为0时就会释放锁
            if (c == 0) {
                free = true;
                //将持有当前锁的线程设置为null,表示没有任何线程持有这把锁
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

非可重入锁源码

 public class ThreadPoolExecutor extends AbstractExecutorService {   
    private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
       //获取锁
       protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true; //非重入锁直接尝试获取锁
            }
            return false;
        }

        //释放锁
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);//释放锁是直接将state设置为0
            return true;
        }
    }
}

五 公平锁和非公平锁

公平是指按照线程请求的顺序来分配锁,而非公平锁指的是,不完全按照请求的顺序,在一定合适的情况下,可以进行插队。

非公平锁的存在是为了提高效率,因为它可以避免线程释放锁后唤醒其他线程时的空档期,

ReentrantLock中的公平锁源码

static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

ReentrantLock中的非公平锁源码

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            //进行CAS操作
            if (compareAndSetState(0, 1))
                //使得当前线程获取锁
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

锁升级与插队策略:

升级

ReentrantReadWriteLock是不允许读锁插队操作,在升降级的时候是只允许写锁将为读锁(降级)而不允许读锁升级为写锁(升级)。

插队策略

为了防止写锁进程进入饥饿状态,读锁不能进行插队。

1. 在锁为公平锁的情况下是不允许插队的,在非公平状态下,当存在多个线程获取读锁后处于同时读取状态,当此时一个线程想要写入时,会因为无法获取锁而进入等待队列,如果增加一个新的读线程时,该线程是可以插队获取读锁,当存在多个读线程进入时,这样写锁会处于饥饿状态。

2.在非公平状态下,当存在多个线程获取读锁后处于同时读取状态,当此时一个线程想要写入时,会因为无法获取锁而进入等待队列,如果增加一个新的读线程时,直接将该线程放入线程队列中,等到写线程完成后才让其获取读锁,这样避免写锁处于饥饿状态。

ReentrantReadWriteLock采用了策略二,但是非公平锁写锁是可以随时插队的,可以插队但是不容易插入。读锁仅在等待队列头结点不是想获取写锁的线程的时候可以插队。

ReentrantReadWriteLock中非公平的实例

    /**
     * Nonfair version of Sync
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            /* As a heuristic to avoid indefinite writer starvation,
             * block if the thread that momentarily appears to be head
             * of queue, if one exists, is a waiting writer.  This is
             * only a probabilistic effect since a new reader will not
             * block if there is a waiting writer behind other enabled
             * readers that have not yet drained from the queue.
             */
            return apparentlyFirstQueuedIsExclusive();
        }
    }

ReentrantReadWriteLock中公平的实例

  /**
     * Fair version of Sync
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

六 共享锁和排它锁

排它锁:又称独占锁和独享锁,只允许一条线程持有,写锁是独享锁的一种。

共享锁:又称为读锁,获得共享锁之后,可以查看当无法对数据进行任何的修改和删除,其他线程也可以获取到共享锁,同样只能查看当无法修改和删除数据

共享锁和排它锁的典型是读写锁ReentrantReadWriteLock,其中读锁是共享锁,写锁是独享锁。通常情况下,Lock只允许一个线程来访问这个共享资源,但是存在一些特殊的实现允许并发访问,比如ReadWriteLock里面的ReadLock。

在没有读写锁之前,我们可以通过过关键字Synchronized或者ReentrantLock进行加锁,这样我们虽然可以保证线程安全,但是也会浪费一定的资源,因为我们对资源仅仅是进行操作,不对数据进行任何的修改时并不存在线程安全问题,而通过这种方式进行加锁的时候无论是读还是写都必须先获取锁,然后进行相应的操作,这样就会造成资源浪费。所有在读的地方使用共享锁,而在写的地方使用写锁,从而对锁进行灵活控制,如果没有写锁,读是无阻塞的,提高了程序的执行效率。

读写锁的申请策略:

  1. 多个线程只申请读锁对资源只进行相应的读操作是都可以申请的;
  2. 如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待读锁的释放;
  3. 如果一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待写锁的释放;

简单的理解,读写锁只是一把锁,可以通过两种方式锁定,读锁定和写锁定。读写锁可以同时被一个或多个线程读锁定,也可以被单一线程写锁定。但是永远不能同时对这把锁进行读锁定和写锁定。

七 锁的升级和降级

某些线程在开始阶段需要进行写入操作,所以持有写锁,而完成写操作之后大部分为读操作,为了避免线程执行任务时出现中断现象,所以线程不会主动直接释放写锁,但是读操作需要的读锁又无法获取,会造成资源的浪费,所以通过锁的降级在不释放写锁的时候直接获取读锁然后再将写锁释放,从而实现读锁的获取。

支持锁的降级,而不支持锁的升级。即写锁可以降级为读锁,但是读锁无法升级为写锁,升级过程会被阻塞。

根据读锁写锁的性质可知,读锁可以被多个线程共同持有,写锁只能由一条线程持有,不能同时存在读锁和写锁,所以在所升级的过程中,需要等待所有的读锁都释放。

如果存在多个读锁都进行升级时,会出现锁的升级过程中的死锁。

八 自旋锁和阻塞锁

阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成,这种状态的切换需要耗费处理时间。当我们同步代码的内容过于简单,状态转换所消耗的时间比用户代码执行的时间还要长。

为了避免同步资源的锁定时间短,需要切换线程,线程挂起和恢复线程的需要消耗的大量时间的情况,所以使用自旋锁。

自旋锁:当物理机存在多个处理器,能够让两个或以上的线程同时并行执行,我们就可以让当前请求锁的线程不放弃CPU的执行时间,并检测是否存在持有锁的线程会很快的释放锁。为了让当前线程完成这部分工作,我们使得当前线程处于自旋状态,如果在自旋完成后前面锁定同步资源的线程已经释放了锁,那么当前线程就可以不必阻塞而是直接获取同步资源,从而避免切换线程的开销。

如果存在自旋时间的过长的情况,甚至比某些线程获取锁到释放锁的时间还要长,那么自旋的线程会出现浪费处理器资源的情况。因为自旋的过程中,会一直消耗CPU,所以虽然自旋锁的起始开销较低,但是随着自旋时间的增长,开销也是线性增长的。

自旋锁的实现,在Atomic包中很多原子类都是通过自旋锁来实现的 ,自旋锁是基于CAS原理实现的,如AtomicInteger中调用unsafe进行自增操作的源码的do-while循环就是一个自旋操作,如果修改过程中遇到其他线程竞争导致没有修改成功,就在while里死循环,直至修改成功。

public class AtomicInteger extends Number implements java.io.Serializable {
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
}

public final class Unsafe {    
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        }
        //自旋操作

         while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
}

阻塞锁:如果当前线程没有获得锁时,就会直接将线程阻塞,然后直到线程被唤醒。

九 可中断锁与不可中断锁

在Java中,synchronized就是不可中断锁,而Lock可以通过tryLock(time)和lockInterruptibly()响应中断来实现可中断锁。

不可中断锁:申请锁的线程会一直等待已经持有锁的线程释放锁,在此期间是不可以执行中断操作的。

可中断锁:如果某一线程A正在执行锁中的代码,另一个线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以中断它。

十 锁的优化

Java虚拟机对锁的优化

  1. 自旋锁和自适锁
  2. 锁消除(对于方法内部的一些私有方法是不可能被外部访问的时候就不需要进行加锁)
  3. 锁粗化:反复的对一个对象进行加锁和解锁操作时候,会将这些加锁和解锁操作合并成一个加锁和解锁操作,JIT编译器会进行检测,如果相邻的synchronized同步代码块使用的是同一个锁对象,它会自动将这些同步代码块合并成一个大的同步代码块,从而在执行的时候无需反复的申请和释放锁,只需要申请一次锁和释放一次锁。

编程过程中的锁优化

  1. 缩小同步代码块:在保证锁中原子操作的同时将开销大且不需要加锁的内容移出同步代码块。
  2. 尽量不要锁住方法:方法的范围可能比较大,而且方法中的内容是会随时被修改的。
  3. 减少锁的次数:如在日志框架中,存在多个线程同时打印日志,由于它们属于互斥所以效率比较低,我们可以将多个线程的任务汇总到一个线程,让后让其统一完成加锁的写操作,类似于使用消息队列作为中间层,此时,我们只需要一个锁来完成日志打印的工作,从而减少锁的申请次数。
  4. 避免人为制造阻塞:如HashMap通过size()方法获取HashMap中数据的数量,当有线程调用size方法时会进行HashMap的遍历操作,此时其他线程修改HashMap的方法就会被阻塞,此时我们可以维护一个HashMap数据量的计数,当往HashMap中插入数据时,计数加一,当从HashMap中移出数据时,计数减一,这样查询时可以直接返回当前的计数而避免使用size()方法造成的阻塞。
  5. 锁中尽量不要再包含锁
  6. 选择合适的锁类型和合适的工具类
C++继承与多态 - 继承多态原理01 C++继承多态原理讲解 阅读详情

相关推荐

c语言面试5(希诺麦田)

在 C 语言中,当使用strlen函数计算字符串的长度时,它会返回字符串中字符的实际个数,不包括字符串结束符’\0’。而sizeof(array)返回的是array指针所占用的字节数,通常在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节。在给定的代码中,array被初始化为"\0\0",其中包含两个转义字符’\0’。当使用strlen函数计算array的长度时,它会遇到第一个’\0’并停止计数,因此返回的长度为 2。12.下面四个选项是四个整数在内存中的存储情况,其中数值最大的一个是。

Pierce110110的博客 1053

【面试题】公平锁和非公平锁、可重入锁

公平锁,在并发环境中,每个线程获取锁的时候会优先查询此锁维护的等待队列,如果为空或者自己是等待队列的第一个直接占有锁,否则加入等待队列。同一线程,在外层方法获取锁后,内层方法自动获取锁。也就是说,线程可以进入任何一个他已经拥有锁同步的方法。多个线程并非按着申请锁的顺序来获取锁,有可能后申请的线程更早获得锁,有可能会造成优先级反转。非公平锁,上来就尝试占有锁,如果尝试失败,再采用类似公平锁的方式。多个线程按着申请锁的顺序来获取锁(类似排队,先来后到)。......

yzx3105的博客 391

深度学习之基于Pytorch手指静脉识别系统(

一、项目背景与目标手指静脉识别技术是一种新兴的生物特征识别技术,它依据人类手指中流动的血液可吸收特定波长的光线这一科学原理,利用手指内的静脉分布图像来进行身份识别。与传统的生物识别技术(如指纹识别)相比,手指静脉识别技术具有不易伪造、识别精度高、非接触性等特点,因此在安全性要求较高的场景(如金融、医疗、公安等)具有广阔的应用前景。本项目旨在利用PyTorch深度学习框架,构建一套高效、准确的手指静脉识别系统。

Q1744828575的博客 830

公平锁与非公平锁、可重入锁(递归锁)、自旋锁、独占锁(写锁)、共享锁(读锁)、互斥锁

文章目录三、自旋锁1.理论2.代码验证①AtomicInteger实现原理CAS②自己编写一个自旋锁3.结论:自旋锁会使线程通过循环比较方式获取锁直到成功为止。四、读写锁1.理论2.代码验证:模拟一个分布式缓存进行多线程读写操作问题:发现不符合写操作的原子+独占3.结论:读写锁ReentrantReadWriteLock可以保证缓存中的读共享,写独占操作 三、自旋锁 四、独占锁(写锁)/共享锁(读锁)/互斥锁 三、自旋锁 1.理论 是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁。 目的:

qq_43357394的博客 2201

Halcon异常检测训练避坑指南:如何避免GPU内存溢出和样本不足问题

本文针对Halcon深度学习异常检测训练中常见的GPU内存溢出和样本不足两大难题,提供了从原理分析到实战解决方案的深度指南。通过调整批次大小、图像尺寸、使用梯度累积等技巧有效管理显存,并利用针对性数据增强与人工合成策略破解小样本困境,帮助开发者构建稳定高效的训练流程。

river的博客 215

【点云数据集】整理汇总(自用,更新ing)

涵盖了各种不同的城市场景:教堂、街道、铁路轨道、广场、村庄、足球场、城堡等等。邮件地址:dmich-request@graphics.stanford.edu,内容需包含:1. 您的姓名、头衔或职位,以及所在机构或隶属关系;license比较难获取,目前可获取的人员:(1)目前隶属于大学、工业研究实验室或其他主要机构的已发表过研究成果的研究人员;普林斯顿 ModelNet 项目的目标是为计算机视觉、计算机图形学、机器人技术和认知科学领域的研究人员提供全面、干净的物体 3D CAD 模型集合。

weixin_44392103的博客 796

java多线程之7嵌套锁的概念

以上内容均来自于本书和我的自己理解的总结 Java Threads, 3rd Edition [Book] (oreilly.com) Nested locks are also supported by the ReentrantLock class—the class that implements the Lock interface that we have been using so far. If a lock request is made by the thread tha.

zy103118的博客 829

2025_NIPS_Truthful Aggregation of LLMs with an Application to Online Advertising

大型语言模型(LLMs)生成内容的 revenue 变现是在线广告的下一个前沿领域。我们考虑这样一种场景:广告商旨在影响LLM的回复,而平台则寻求最大化广告商价值并确保用户满意度。核心挑战在于,广告商的偏好通常与用户偏好存在冲突,且广告商可能误报其偏好。为解决这一问题,我们提出MOSAIC——一种拍卖机制,它确保真实申报是广告商的占优策略,并使每个广告商的效用与其对社会福利的贡献保持一致。重要的是,该机制无需LLM微调或访问模型权重,且随着计算资源的增加,可证明收敛到最优微调LLM的输出。

c_cpp_csharp的专栏 80

公平锁/非公平锁/可重入锁/递归锁/自旋锁/独占锁/共享锁/互斥锁

1. 公平锁和非公平锁 公平锁:是指多个线程按照申请锁的顺序来获取锁,类似排队打饭 ,先来后到。 非公平锁:是指在多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情况下,有可能造成优先级反转或者饥饿现象。 对于synchronized而言 也是一种非公平锁。 并发包ReentrantLock的创建可以指定构造函数的boolean类型来得到公平锁或者非公平锁 默认是非公平锁。 空参构造器:非公平锁 带参构造器:公平锁 2. 可重入锁(又名递归锁

weixin_42480780的博客 619

【CANdelaStudio编辑CDD】-2.2-给$27服务SecurityAccess创建一个SecurityLevel安全级别并修改SecurityAccess安全访问状态机(UDS诊断)

前一篇: 【UDS诊断描述文件CDD】-2.1-ISO_14229中$27服务理论部分https://blog.youkuaiyun.com/qfmzhu/article/details/120392660 案例背景: 在CDD中如何给$27服务创建一个新的SecurityLevel安全级别; 在CDD中如何给$27服务修改SecurityAccess安全访问状态机。 1 查看$27服务中已有的SecurityLevel安全级别 2 查看$27服务中已有的SecurityAccess安全...

「汽车电子助手」的博客 4641

彩票的未来:基于人工智能与大数据的创新预测模型

随着人工智能(AI)和大数据技术的迅猛发展,彩票行业正面临前所未有的变革。本文将探索如何通过结合深度学习、机器学习和数据挖掘技术,构建先进的预测模型,以提高彩票开奖结果的预测准确性。通过分析历史数据、应用现代化的计算技术,我们提出了一种创新的彩票预测软件架构,旨在推动彩票行业向着更加智能和高效的方向发展。

Sapphire521的博客 1439

JUC学习笔记

1.SaleTicket //资源类 = 实例变量 + 实例方法 class Ticket{ //票 private int number = 30; Lock lock = new ReentrantLock(); public void sale(){ lock.lock(); try { if (number > 0){ System.out.println(Thread.

lizongxiao的博客 1万+

深入浅出:使用Python爬取链家二手房数据

在数据驱动的时代,房地产数据作为社会经济的重要指标,一直是数据分析师、投资者和研究人员关注的焦点。链家作为国内领先的房产中介平台,其二手房数据具有较高的真实性和时效性。然而,官方API的访问限制和数据获取的门槛,让很多初学者望而却步。本文将带你从零开始,使用Python编写一个符合robots.txt规范的链家二手房爬虫,获取标题、户型、价格等信息。文章不仅会提供完整代码,还会深入讲解反爬策略、请求头伪装、数据解析、异常处理等实战技术。目录前言:为什么要写这篇博客?一、爬虫前的准备:法律与道德。

2201_76125261的博客 90

解锁Java面试中的锁:深入了解不同类型的锁和它们的用途

锁及其应用。锁在多线程编程中扮演着重要的角色,确保共享资源的安全访问,同时也影响到应用程序的性能和可伸缩性。了解不同类型的锁以及它们的用途对于编写多线程程序至关重要。通过谨慎选择和正确使用锁,开发人员可以确保应用程序的正确性、性能和可伸缩性。在多线程编程中,锁是实现线程安全的关键工具,也是高效并发的基础。更多内容请参考最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

程序那些事 392

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java锁Synchronized不同用法的区别

一、Synchronized锁用法示例: 1)加在方法上: 非静态方法:public synchronized void test(){...} 静态方法: public static synchronized void test2(){...} 2)加在代码锁 类锁 public void test(){ ... synchronized (ObjLockTest.class){ ... } ... } 对象锁 public void .

ArtisticProgramming的博客 504

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Java三种不同的锁

Java中,锁分为乐观锁和悲观锁两类(数据库乐观锁和悲观锁参考 http://blog.youkuaiyun.com/liupeng_qwert/article/details/72935469)悲观锁:直接将在并发情况下可能出问题的代码加同步,同一时刻只允许一个线程访问,典型的代表是synchronized 乐观锁:每次不加锁去执行某项操作,如果发生冲突则失败并重试,直到成功为止,也称之为【自旋】

liupeng_qwert的专栏 610

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

java“锁事“ 之不同的锁讲解

java的各种锁的介绍

一个有信仰的技术人 157

java中synchronized加不同锁时其包括的语句是否还是原子的

今天学习了java的加锁机制,介绍了关键词synchronized;课上说使用这个关键字词可以将一段代码原子化,在多线程的程序执行中使这段代码无法被拆分。 对于synchronized后面接同样的对象(同样的锁)的语句块,毫无疑问,其后的语句块是原子的,不可被拆分,相当于被线性的执行。 但是对于synchronized后面接不通的对象时(不通的锁),后面的语句块是否还是原子的,不可被拆分的? 所以写了如下的代码: import java.util.ArrayList; import java.util.re

qq_43323545的博客 315

Java不同锁的基本原理

深入理解Java中的多种锁 乐观锁与悲观锁 独占锁与共享锁 互斥锁与读写锁 公平锁与非公平锁 可重入锁 自旋锁 分段锁 乐观锁与悲观锁 悲观锁 悲观锁顾名思义,对应的是十分悲观的东西,这个锁无论对任何东西进行操作,都会认为会有人进行插队,所以这个锁会进行上锁。 那么其他人只能在对象等待池里进行等待,这种状态也就是阻塞了。 进入到java代码世界中,也就是说只要有对象被悲观锁进行占有,那么其他想要对这个对象进行操作的锁都会在外面进行 等待那就只能阻塞了。 在对应的java语言中对应的悲观锁即为关键字Sy

m0_46415190的博客 227

您真的了解Java中的锁吗?这7种不同维度下的锁知道吗?

OK,今天关于锁的介绍就写到这里啦,本文先做一个总体上的概括,在后续的更新中会做详细介绍呀!😊。

JavaBuild的博客 769

Java用户锁-针对不同用户不同的锁

场景:用户点赞、取消点赞。 问题:避免点赞与取消点赞冲突,在不考虑其他方法前提下,采用JAVA synchronized 进行同步锁操作,如果直接锁方法,那A用户点赞、取消点赞时,会导致其他用户无法点赞、取消点赞。所以采用锁用户ID的形式 public static void main(String[] args) { // System.out.println(DigestUtils.md5DigestAsHex(("20210928#888" + "1010").getBytes

qq_24973007的博客 2183

java synchronized int_java synchronized锁不同class的区别是什么

好多人说没有区别,这样吧,直接上代码和结果吧public class Test {static Runnable lock = new Runnable() {@Overridepublic void run() {synchronized (A.class) {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printSta...

weixin_34476045的博客 174

Java基础学习之并发篇:不同的锁的适用场景

前言 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。 Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录: 1.乐观锁 VS 悲观锁# 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的

h16407的博客 995

JAVA基础:Lock不同的锁形式

假设, 有n个线程同时访问同步资源,只有1个线程可以获得锁,其他n-1个线程进入同步队列,等待。当第一个线程释放锁资源后, 同步队列中那n-1个线程,会按顺序依次获得锁 (倒序 或 顺序)排它锁又称为 互斥锁,也称为 独享锁,当一个线程获得该锁, 其他线程无法获得锁,需要等待。当线程1进入同步代码段时,会记录线程1的信息,表示线程1获得了锁,同时锁状态0 - 1。如果之前记录的线程信息和当前进入的线程信息相同,说明重入,允许,同时状态1 - 2。这个新线程,直接进入同步队列,等待前面的线程释放锁。

weixin_53755148的博客 664

java在不同情况下锁对象探索

先从最简单的开始 *************************************** 分割线   demo1 *************************************** public static void main(String args[]){ final Class1 c1 = new Class1(); Thread t1 =

perfectnihil的博客 383

cas客户端登陆状态不同步_Java中的锁[原理、锁优化、CAS、AQS]

作者:高广超链接:https://www.jianshu.com/p/e674ee68fd3f1、为什么要用锁?锁-是为了解决并发操作引起的脏读、数据不一致的问题。2、锁实现的基本原理2.1、volatile★Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便...

weixin_29123181的博客 97
上一篇: 我意识中的AQS(AbstractQueuedSynchronizer)以及几种同步类(器)
下一篇: HashMap,Vector,Hashtable,ConcurrentHashMap等并发容器线程安全的进化过程
至学者
博客等级 码龄9年 180粉丝 773原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值