iOS--锁的学习

iOS--锁的学习

  • 锁的介绍
    • 线程安全
  • 锁的分类
    • 自旋锁和互斥锁
    • OSSpinLock
    • os_unfair_lock
    • pthread_mutex
      • pthread_mutex的属性
    • NSLock
    • NSRecursiveLock
    • NSCondition
    • NSConditionLock
    • dispatch_semaphore
    • dispatch_queue
    • @synchronized
    • atomic
    • pthread_rwlock:读写锁
    • dispatch_barrier_async
  • 锁的性能比较

锁的介绍

主要参考了iOS多线程安全-13种线程锁🔒
在iOS开发中,锁是一种用于管理并发访问共享资源的机制。多个线程可以同时访问共享资源,但在某一时刻只允许一个线程对资源进行读取或修改,以避免数据竞争和不一致性。
锁的主要目的是确保在给定时间内只有一个线程可以进入被锁定的代码块或临界区。当一个线程获得了锁并进入临界区时,其他尝试获取锁的线程会被阻塞,直到该线程释放锁。这样可以保证在临界区内的代码只会被一个线程执行,从而避免竞态条件和数据不一致性的问题。

在iOS中,有多种锁机制可供选择,每种锁机制都有其特定的适用场景和性能特征。一些常见的锁机制包括:
互斥锁(Mutex):例如NSLock、pthread_mutex等。互斥锁提供了基本的线程同步机制,通过对临界区加锁和解锁来确保同一时间只有一个线程可以访问。
递归锁(Recursive Lock):例如NSRecursiveLock、pthread_mutex_recursive等。递归锁允许同一线程多次获取锁,避免了死锁情况。
条件锁(Condition Lock):例如NSConditionLock、pthread_cond等。条件锁在某些特定条件下才允许线程继续执行,否则线程会被阻塞。
信号量(Semaphore):例如dispatch_semaphore。信号量是一种更为通用的同步机制,可以用于控制多个线程的并发数量。
自旋锁(Spin Lock):例如os_unfair_lock、OSSpinLock(已被弃用)等。自旋锁在等待锁时不会将线程阻塞,而是通过循环忙等的方式尝试获取锁,适用于短时间内锁的竞争概率较低的情况。

线程安全

线程安全是指在多线程环境下,程序能够正确地处理共享数据并保证数据的一致性和正确性。
在多线程编程中,多个线程可以同时访问和修改共享的数据。如果没有适当的同步机制和线程安全的设计,可能会出现以下问题:

  • 竞态条件(Race Condition):多个线程同时对同一数据进行读写操作,导致结果依赖于线程执行的顺序,从而得到不确定的结果。
  • 数据竞争(Data Race):多个线程同时访问和修改共享数据,其中至少一个是写操作,导致未定义的行为。

这里用一个比较经典的例子,具体参考iOS多线程安全-13种线程锁🔒

//卖票演示
- (void)ticketTest{
self.ticketsCount = 50;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {
dispatch_async(queue, ^{
for (int i = 0; i < 10; i++) {
[self sellingTickets];
}
});
}

}
//卖票
- (void)sellingTickets{
int oldMoney = self.ticketsCount;
sleep(.2);
oldMoney -= 1;
self.ticketsCount = oldMoney;

NSLog(@"当前剩余票数-> %d", oldMoney);
}

运行结果如图:
在这里插入图片描述

这里是一个典型的数据竞争问题,当多个线程同时对一个共享数据进行读写操作是很有可能会发生数据竞争,为了避免这种情况,我们往往通过线程同步来保证线程安全。实现线程同步的方法很多,锁就是一种比较常见的用法 ;

锁的分类

锁是实现线程同步和保证数据访问的一种机制,在多线程编程中起着重要的作用。根据实现方式和特性,锁可以分为几个不同的分类:

  • 互斥锁(Mutex
    Lock):互斥锁是最常见和基本的锁类型,用于实现互斥访问共享资源。它提供了两个状态:锁定(被一个线程持有)和解锁(无线程持有)。只有一个线程可以持有互斥锁,其他线程在获取锁之前会被阻塞。互斥锁可以防止多个线程同时访问临界区,从而保证数据的一致性。
  • 读写锁(Read-Write
    Lock):读写锁也称为共享-独占锁,它允许多个线程同时读取共享资源,但只允许一个线程进行写操作。读操作之间不会互斥,而读操作与写操作之间是互斥的。读写锁适用于读多写少的场景,可以提高并发性能。
  • 自旋锁(Spin
    Lock):自旋锁是一种忙等待锁,它使用循环来反复检查锁是否被释放,而不是将线程阻塞。当一个线程发现自旋锁被其他线程持有时,它会一直循环等待,直到自旋锁可用。自旋锁适用于临界区很小且短时间内会释放的情况。
  • 条件变量(Condition
    Variable):条件变量用于线程之间的等待和通知机制。它与互斥锁结合使用,允许一个线程等待某个条件成立并在条件满足时通知其他线程。等待条件的线程会释放互斥锁,以便其他线程可以访问临界区。条件变量常用于生产者-消费者问题等场景。
  • 屏障(Barrier):屏障用于多个线程在某个点上等待,直到所有线程都到达该点后才继续执行。它可以用于同步多个线程的操作,确保线程在达到某个阶段之前都等待其他线程。

自旋锁和互斥锁

自旋锁(Spin Lock):
自旋锁是一种忙等待锁,它使用循环来反复检查锁的状态,直到获取到锁为止。自旋锁的特点如下:

  • 自旋锁适用于临界区很小且短时间内会释放的情况,因为它需要持续占用CPU资源来进行自旋等待。
  • 自旋锁不会导致线程的阻塞和切换,所以对于短时间内能够获取到锁的情况,自旋锁的性能较好。
  • 自旋锁不会改变线程的调度顺序,因此在高优先级线程和低优先级线程之间,可能会导致优先级反转的问题。

互斥锁是一种常见的线程同步机制,用于实现互斥访问共享资源。在iOS中,常用的互斥锁有NSLock和NSRecursiveLock。互斥锁的特点如下:

  • 互斥锁允许一个线程持有锁,其他线程在获取锁之前会被阻塞,从而实现对临界区的互斥访问。
  • 互斥锁会导致线程的阻塞和切换,所以对于长时间占用锁或等待时间不确定的情况,互斥锁的性能可能较差。
  • 互斥锁可以解决优先级反转的问题,因为它可以改变线程的调度顺序,让优先级高的线程优先获取锁。

互斥锁:线程会从sleep(加锁)——>running(解锁),过程中有上下文的切换,cpu的抢占,信号的发送等开销。
自旋锁:线程一直是running(加锁——>解锁),死循环检测锁的标志位,机制不复杂。
对比
互斥锁的起始原始开销要高于自旋锁,但是基本是一劳永逸,临界区持锁时间的大小并不会对互斥锁的开销造成影响,而自旋锁是死循环检测,加锁全程消耗cpu,起始开销虽然低于互斥锁,但是随着持锁时间,加锁的开销是线性增长。

OSSpinLock

OSSpinLock是iOS旧版本中提供的一种自旋锁(Spin Lock)实现。它通过忙等待的方式来获取锁,并且不会导致线程的阻塞和切换。不过需要注意的是,自旋锁在iOS 10之后已被标记为废弃,因为它存在优先级反转和性能问题。推荐使用更现代的互斥锁实现,如os_unfair_lock和pthread_mutex等。
使用时需要导入头文件#import <libkern/OSAtomic.h>
在这里插入图片描述

os_unfair_lock

os_unfair_lock是iOS 10及以上版本引入的一种互斥锁(Mutex Lock)实现,用于实现线程同步和保护共享资源的访问。相比于旧版本中的自旋锁(OSSpinLock),os_unfair_lock采用了更高级的算法来解决优先级反转和性能问题。
os_unfair_lock的特点如下:

  • os_unfair_lock是一种互斥锁,只能由一个线程持有,其他线程在获取锁之前会被阻塞。
  • 它可以解决优先级反转问题,确保高优先级线程在等待锁时能够优先获取。
  • os_unfair_lock的实现采用了更高级的算法,避免了自旋等待,减少了不必要的CPU开销。
  • os_unfair_lock的性能通常比旧版自旋锁(OSSpinLock)更好,尤其在高并发情况下。
    需要导入头文件#import <os/lock.h>
@implementation ViewController {
    os_unfair_lock _lock ;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self ticketTest] ;


}

//卖票演示
- (void)ticketTest{
self.ticketsCount = 50;
//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;
    _lock = OS_UNFAIR_LOCK_INIT ;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {

            [self sellingTickets];

            }
        });
    }

}
//卖票
- (void)sellingTickets{
    os_unfair_lock_lock(&_lock) ;
    int oldMoney = self.ticketsCount;
    sleep(.2);
    oldMoney -= 1;
    self.ticketsCount = oldMoney;
    NSLog(@"当前剩余票数-> %d", oldMoney);
    os_unfair_lock_unlock(&_lock) ;
}



@end

在这里插入图片描述

要注意一下,通常不建议将 os_unfair_lock 直接作为属性来使用。os_unfair_lock 是一个结构体,不具备 Objective-C 对象的特性,因此不适合直接作为属性。

pthread_mutex

pthread_mutex 是 POSIX 线程库中提供的一种互斥锁(mutex)类型,用于实现线程同步和互斥访问共享资源。
主要的 pthread_mutex 函数如下:

  • pthread_mutex_init:用于初始化互斥锁,并指定互斥锁的属性。可以使用 NULL 作为第二个参数来使用默认属性。
  • pthread_mutex_destroy:用于销毁互斥锁。
  • pthread_mutex_lock:加锁操作,将互斥锁加锁,如果互斥锁已经被其他线程锁定,则当前线程被阻塞直到互斥锁可用。
  • pthread_mutex_trylock:尝试加锁操作,如果互斥锁已经被其他线程锁定,则该操作会立即返回,而不会阻塞当前线程。
  • pthread_mutex_unlock:解锁操作,释放互斥锁,允许其他线程获得锁。
@implementation ViewController {
//    os_unfair_lock _lock ;
    pthread_mutex_t _lock ;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self ticketTest] ;


}

//卖票演示
- (void)ticketTest{
self.ticketsCount = 50;
//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;
//初始化锁属性
    pthread_mutexattr_t attr ;
    pthread_mutexattr_init(&attr) ;
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;
    pthread_mutex_init(&_lock, &attr) ;//第二个参数可以为NULL,表示使用默认属性PTHREAD_MUTEX_NORMAL

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {

            [self sellingTickets];

            }
        });
    }

}
//卖票
- (void)sellingTickets{
//    os_unfair_lock_lock(&_lock) ;
    pthread_mutex_lock(&_lock) ;
    int oldMoney = self.ticketsCount;
    sleep(.2);
    oldMoney -= 1;
    self.ticketsCount = oldMoney;
    NSLog(@"当前剩余票数-> %d", oldMoney);
//    os_unfair_lock_unlock(&_lock) ;
    pthread_mutex_unlock(&_lock) ;
}



@end

在这里插入图片描述

pthread_mutex的属性

pthread_mutexattr_settype:设置互斥锁的类型。常见选项有:

  • PTHREAD_MUTEX_NORMAL:普通互斥锁,不支持递归。
  • PTHREAD_MUTEX_RECURSIVE:递归互斥锁,允许同一线程多次获得锁。
  • PTHREAD_MUTEX_ERRORCHECK:错误检查互斥锁,会检测多次锁定同一互斥锁的错误。
  • PTHREAD_MUTEX_DEFAULT:根据实现的默认类型设置互斥锁。

NSLock

**NSLock是对mutex普通锁的封装。**pthread_mutex_init(mutex, NULL);
NSLock 遵循 NSLocking 协议。Lock 方法是加锁,unlock 是解锁,tryLock 是尝试加锁,如果失败的话返回 NO,lockBeforeDate: 是在指定Date之前尝试加锁,如果在指定时间之前都不能加锁,则返回NO

@protocol NSLocking
- (void)lock;
- (void)unlock;
@end

@interface NSLock : NSObject <NSLocking> {
@private
void *_priv;
}

- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;
@property (nullable, copy) NSString *name
@end

@implementation ViewController {
//    os_unfair_lock _lock ;
//    pthread_mutex_t _lock ;
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self ticketTest] ;


}

//卖票演示
- (void)ticketTest{
self.ticketsCount = 50;
//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;
//初始化锁属性
//    pthread_mutexattr_t attr ;
//    pthread_mutexattr_init(&attr) ;
//    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;
//    pthread_mutex_init(&_lock, &attr) ;//第二个参数可以为NULL,表示使用默认属性PTHREAD_MUTEX_NORMAL

    self.lock = [[NSLock alloc] init] ;
    
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {

            [self sellingTickets];

            }
        });
    }

}
//卖票
- (void)sellingTickets{
//    os_unfair_lock_lock(&_lock) ;
//    pthread_mutex_lock(&_lock) ;
    [self.lock lock] ;
    int oldMoney = self.ticketsCount;
    sleep(.2);
    oldMoney -= 1;
    self.ticketsCount = oldMoney;
    NSLog(@"当前剩余票数-> %d", oldMoney);
//    os_unfair_lock_unlock(&_lock) ;
//    pthread_mutex_unlock(&_lock) ;
    [self.lock unlock] ;
}

//- (instancetype)init {
//    self = [super init];
//    if (self) {
//        _lock = [[NSLock alloc] init];
//    }
//    return self;
//}

//- (void)lock {
//    [_lock lock];
//}
//
//- (void)unlock {
//    [_lock unlock];
//}

@end

在这里插入图片描述

NSRecursiveLock

NSRecursiveLock是对mutex递归锁的封装,API跟NSLock基本一致

- (void)ticketTest{
self.ticketsCount = 50;
//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;
//初始化锁属性
//    pthread_mutexattr_t attr ;
//    pthread_mutexattr_init(&attr) ;
//    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;
//    pthread_mutex_init(&_lock, &attr) ;//第二个参数可以为NULL,表示使用默认属性PTHREAD_MUTEX_NORMAL

    self.lock = [[NSRecursiveLock alloc] init] ;
    
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {

            [self sellingTickets];

            }
        });
    }

}
//卖票
- (void)sellingTickets{
//    os_unfair_lock_lock(&_lock) ;
//    pthread_mutex_lock(&_lock) ;
    [self.lock lock] ;
    int oldMoney = self.ticketsCount;
    sleep(.2);
    oldMoney -= 1;
    self.ticketsCount = oldMoney;
    NSLog(@"当前剩余票数-> %d", oldMoney);
//    os_unfair_lock_unlock(&_lock) ;
//    pthread_mutex_unlock(&_lock) ;
    [self.lock unlock] ;
}

NSCondition

NSCondition是对mutex和cond的封装,更加面向对象 ;

@interface NSCondition : NSObject <NSLocking>

- (void)wait;
- (BOOL)waitUntilDate:(NSDate *)limit;
- (void)signal;
- (void)broadcast;

@property (nullable, copy) NSString *name;

@end
  • NSCondition 类继承自 NSObject 并遵循 NSLocking 协议。
  • wait 方法用于使当前线程等待,直到接收到信号。 waitUntilDate: 方法使当前线程等待,直到接收到信号或者指定的日期超时。
  • signal 方法用于唤醒一个等待中的线程。
  • broadcast 方法用于唤醒所有等待中的线程。
  • name 属性是一个可选的字符串,用于标识 NSCondition 对象的名称。
// 线程1
// 删除数组中的元素
- (void)__remove
{
[self.condition lock];
if (self.data.count == 0) {
// 等待
[self.condition wait];
}
[self.data removeLastObject];
NSLog(@"删除了元素");
[self.condition unlock];
}

// 线程2
// 往数组中添加元素
- (void)__add
{
[self.condition lock];
sleep(1);
[self.data addObject:@"Test"];
NSLog(@"添加了元素");
// 信号
[self.condition signal];
[self.condition unlock];
}

我的想法是这类对象有两种线程等待的方式,一种是wait–signal方式,一种是lock–unlock方式 ;

NSConditionLock

NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值

@interface NSConditionLock : NSObject <NSLocking> {
 
- (instancetype)initWithCondition:(NSInteger)condition;

@property (readonly) NSInteger condition;
- (void)lockWhenCondition:(NSInteger)condition;
- (BOOL)tryLock;
- (BOOL)tryLockWhenCondition:(NSInteger)condition;
- (void)unlockWithCondition:(NSInteger)condition;
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;
@property (nullable, copy) NSString *name;
@end

dispatch_semaphore

ispatch_semaphore 是 Grand Central Dispatch (GCD) 中的一个信号量机制,用于控制并发访问共享资源的线程数量。这个之前GCD中讲过了 ;

dispatch_queue

使用GCD的串行队列也可以实现线程同步的

@synchronized

@synchronized 是 Objective-C 中用于实现线程安全的关键字之一。它提供了一种简单的方式来保护共享资源,以防止多个线程同时访问和修改该资源。
使用 @synchronized 的基本语法如下:

@synchronized (object) {
    // 同步的代码块
    // ...
}

@synchronized 关键字的工作原理是,在进入 @synchronized 代码块之前,它会获取 object 的互斥锁,以确保同一时间只有一个线程可以进入该代码块。当线程离开 @synchronized 代码块时,它会释放锁,允许其他线程继续进入。

关于@synchronized 的底层原理可以去深入看看,但平时使用只要知道它会在代码块开头加锁,代码块末尾解锁就行了

atomic

在Objective-C中,atomic是一种属性修饰符,用于指定属性的原子性。当一个属性被声明为atomic时,它意味着在对该属性进行读取和写入操作时,将会保证操作的原子性。
原子性是指一个操作要么完全执行,要么完全不执行,不存在执行过程中被中断的情况。在多线程环境下,使用atomic修饰符可以确保对属性的读取和写入操作是线程安全的。
当属性被声明为atomic时,编译器会自动生成相关的同步代码,以确保对属性的访问是原子操作。这样可以防止多个线程同时对同一个属性进行读写操作,避免出现数据竞争和不一致的情况。
需要注意的是,虽然atomic提供了一定程度的线程安全性,但它并不能完全保证线程安全。在高并发的多线程环境中,仍然需要额外的同步机制来确保数据的一致性和正确性。
相比之下,另一个属性修饰符nonatomic则表示属性是非原子的,它不会提供自动的线程安全保护。在多线程环境下,使用nonatomic修饰符可以提高性能,但需要开发人员自行处理线程安全问题。
总之,atomic属性修饰符用于指定属性的原子性,提供一定程度的线程安全性。在多线程环境中,可以使用atomic来确保对属性的读取和写入操作是原子的,但仍需要注意其他的线程安全问题。

pthread_rwlock:读写锁

//初始化锁
pthread_rwlock_t lock;
pthread_rwlock_init(&_lock, NULL);

//读加锁
pthread_rwlock_rdlock(&_lock);
//读尝试加锁
pthread_rwlock_trywrlock(&_lock)

//写加锁
pthread_rwlock_wrlock(&_lock);
//写尝试加锁
pthread_rwlock_trywrlock(&_lock)

//解锁
pthread_rwlock_unlock(&_lock);
//销毁
pthread_rwlock_destroy(&_lock);


pthread_rwlock 是 POSIX 线程库中的读写锁(read-write lock)机制。它提供了一种多读单写的并发访问控制机制,允许多个线程同时读取共享资源,但只允许一个线程进行写操作。
使用 pthread_rwlock 可以实现以下功能:

  • 多读单写控制:多个线程可以同时获取读锁(读取共享资源),但只有一个线程可以获取写锁(修改共享资源)。
  • 读写互斥:在写锁被持有期间,其他线程无法获取读锁,以确保数据一致性。

dispatch_barrier_async

GCD中也有 ;

锁的性能比较

性能从高到低排序

1、os_unfair_lock
2、OSSpinLock
3、dispatch_semaphore
4、pthread_mutex
5、dispatch_queue(DISPATCH_QUEUE_SERIAL)
6、NSLock
7、NSCondition
8、pthread_mutex(recursive)
9、NSRecursiveLock
10、NSConditionLock
11、@synchronized

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/645946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

S1E45:单链表1 课后作业

测试题&#xff1a;0. 相比起数组来说&#xff0c;单链表具有哪些优势呢&#xff1f; 答&#xff1a;长度非固定&#xff0c;可以申请添加长度 答案&#xff1a;对于数组来说&#xff0c;随机插入或者删除其中间的某一个元素&#xff0c;都是需要大量的移动操作&#xff0c;而…

Vue.Draggable:强大的Vue拖放组件技术探索

一、引言 随着前端技术的不断发展&#xff0c;拖放&#xff08;Drag-and-Drop&#xff09;功能已经成为许多Web应用不可或缺的一部分。Vue.js作为现代前端框架的佼佼者&#xff0c;为开发者提供了丰富的生态系统和强大的工具链。Vue.Draggable作为基于Sortable.js的Vue拖放组件…

在二十三届中国科学家论坛大会上,郎百忠被授予《中国首席政治书法领域科学家》荣誉称号

在5月25日于北京举办的第二十三届中国科学家论坛上&#xff0c;备受瞩目的书法家郎百忠凭借其卓越的书法造诣和深厚的政治素养&#xff0c;荣获了"中国首席政治书法科学家"称号。这一荣誉是对郎百忠多年来在书法领域的杰出贡献以及他在政治书法领域的卓越成就的肯定。…

leedcode【19】. 删除链表的倒数第 N 个结点——Java解法

Problem: 19. 删除链表的倒数第 N 个结点 思路解题方法复杂度Code性能 思路 如果要删除倒数第n个节点&#xff0c;让fast移动n步&#xff0c;然后让fast和slow同时移动&#xff0c;直到fast指向链表末尾。删掉slow所指向的节点就可以了。 分为如下几步&#xff1a; 定义fast指…

AI重塑保险业未来:机器学习在风险评估、欺诈检测与客户服务中的深度应用

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

Adobe Bridge BR v14.0.3 安装教程 (多媒体文件组织管理工具)

Adobe系列软件安装目录 一、Adobe Photoshop PS 25.6.0 安装教程 (最流行的图像设计软件) 二、Adobe Media Encoder ME v24.3.0 安装教程 (视频和音频编码渲染工具) 三、Adobe Premiere Pro v24.3.0 安装教程 (领先的视频编辑软件) 四、Adobe After Effects AE v24.3.0 安装…

C/C++ vector详解

要想了解STL&#xff0c;就必须会看&#xff1a; cplusplus.comhttps://legacy.cplusplus.com/ 官方内容全都是英文的&#xff0c;可以参考&#xff1a; C/C初始识https://blog.csdn.net/2301_77087344/article/details/138596294?spm1001.2014.3001.5501 vector&#xff…

【LakeHouse】Apache Iceberg + Amoro 助力网易构建云原生湖仓

Apache Iceberg Amoro 助力网易构建云原生湖仓 1.云原生湖仓背景与挑战2.Apache Iceberg 、Amoro 与云原生2.1 Apache Iceberg2.2 Amoro 简介 3.Apache Iceberg Amoro 云原生实践3.1 云上湖仓案例一3.2 云上湖仓案例二3.3 云上湖仓案例三 4.Amoro 未来发展规划 出品社区&…

Dubbo生态之nacos

1.Nacos简介 在博客Dubbo生态之初识dubbo协议-CSDN博客种我们已经介绍了为什么要使用注册中心&#xff0c;nacos作为注册中心的一种&#xff0c;相对于其它的主流注册中心有什么区别呢? NacosEurekaZookeeper数据存储存储在内存存储在内存存储在内存通信协议gRPChttpjute协议…

Yolov9调用COCOAPI生成APs,APm,APl

最近在做小目标检测的东西&#xff0c;因为后期毕业论文需要&#xff0c;所以开始使用Yolov9模型&#xff0c;运行val.py的时候不会自己产生小目标的AP指标&#xff0c;所以研究了一下&#xff0c;步骤非常简单&#xff1a; 第一步&#xff1a; 在数据集中生成json格式的Annota…

ISCC2024个人挑战赛WP-DLLCode

&#xff08;非官方解&#xff0c;以下内容均互联网收集的信息和个人思路&#xff0c;仅供学习参考&#xff09; 注意到程序调用了Encode函数对明文进行加密&#xff0c;点进去发现是对外部DLL的调用 静态分析DLL中的Encode函数可以得到 写出对应的解密脚本如下 #include <…

【三维修复、分割与编辑】InFusion、Bootstrap 3D、GaussianGrouping、GaussianEditor等(论文总结)

提示&#xff1a; 文章目录 前言一、InFusion&#xff1a;扩散模型助力&#xff0c;效率提高20倍&#xff01;(2024)1. 摘要2. 算法3. 效果 二、2D Gaussian Splatting三、Bootstrap 3D:从扩散模型引导三维重建1.摘要2.相关工作3.方法1.Boostrapping by Diffusion 通过扩散模型…

搭建访问阿里云百炼大模型环境

最近这波大降价&#xff0c;还有限时免费&#xff0c;还不赶快试试在线大模型&#xff1f;下面整理访问百炼平台的千问模型方法。 创建RAM子账号并授权 创建RAM子账号 1. “访问控制RAM”入口&#xff08;控制台URL&#xff09; 然后点击进入“RAM管理控制台” 2. 添加用户 …

漫谈企业信息化安全-综述

一、前言 一直以来想写一些文章&#xff0c;谈一谈企业信息化过程中的安全问题及对策。 随着信息技术的不断发展和普及&#xff0c;特别是今年来移动办公、云服务等等新的工作模式和新的信息技术的应用&#xff0c;企业信息化已经成为提升竞争力、促进创新和发展的重要途径。…

Spark-RDD-依赖关系详解

Spark概述 Spark-RDD概述 Spark-RDD-依赖关系 在Apache Spark中&#xff0c;RDD&#xff08;Resilient Distributed Dataset&#xff09;是一种基本的抽象数据结构&#xff0c;代表了分布式的、不可变的数据集。 RDD之间的依赖关系在Spark中非常重要&#xff0c;因为它们决定了…

MySQL 存储过程(实验报告)

一、实验名称&#xff1a; 存储过程 二、实验日期&#xff1a; 2024 年5 月 25 日 三、实验目的&#xff1a; 掌握MySQL存储过程的创建及调用&#xff1b; 四、实验用的仪器和材料&#xff1a; 硬件&#xff1a;PC电脑一台&#xff1b; 配置&#xff1a;内存&#xff0…

mysql事务 事务并发问题 隔离级别 以及原理

mysql事务 简介&#xff1a;事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 事务四大特性 原子性&#xff08;Atomici…

多模态交互式 AI 代理的兴起:探索 Google 的 Astra 和 OpenAI 的 ChatGPT-4o应用

OpenAI的发展 聊天GPT-4o 和 谷歌的阿斯特拉 标志着交互式人工智能代理的新阶段&#xff1a;多模式交互式人工智能代理的兴起。这次旅程开始于 Siri 和 Alexa的&#xff0c;它将语音激活的人工智能带入主流用途&#xff0c;并通过语音命令改变了我们与技术的交互。尽管有影响&a…

链表类型的无界阻塞线程安全队列-ConcurrentLinkedQueue(FIFO)

ConcurrentLinkedQueue是非阻塞线程安全(volatile不能完全保证线程安全)的队列,适用于“高并发”的场景。是一个基于链表节点的无界线程安全队列,按照 FIFO(先进先出,尾先进头先出)原则对元素进行排序。队列元素中不可以放置null元素(内部实现的特殊节点除外)。 volati…

linux笔记6--shell相关

文章目录 1. 查看当前的shell类型2. ps -f命令3. 父子shell4. 分号在命令里的作用问题&#xff1a;环境变量echo&#xff1a; 5. sleep和jobssleep:jobs:例子&#xff1a;&: 6. 外部命令和内建命令图解外部命令type命令 7. history命令8. alias命令9. 推荐 1. 查看当前的sh…