静态初始化 // 定义 static { ... } 静态初始化块执行的优先级高于非静态初始化块,在对象装载到JVM中时执行一次,仅能初始化类成员变量,即static修饰的数据成员。 3. 非静态初始化 // 定义 { ... } 非静态初始化块在每个对象生成时都会被执行一次,它可以初始化类的实例变量。非静态初始化块在构造函数之前执行。 4. 总结 从某种程度上来看,初始化块是构造器的补充,初始化块总是在构造器之前执行。初始化块是一段固定执行的代码,它不能接受任何参数。因此初始化块对同一个类的所有对象所进行的初始化处理完全相同。 如果有一段初始化处理代码对所有的对象完全相同,且无需接受任何参数,就可以把这段初始化处理代码提取到初始化块中。通过把多个构造器中的相同代码提取到初始化块中定义,能更好地提高初始化代码的复用。 静态初始化块是类相关的,系统将在类加载时执行静态初始化块,而不是在创建对象时才执行,因此静态初始化块总是比非静态初始化块先执行。用途:例如在JNI调用时,需要加载动态链接库,就可以在静态代码块中加载。
//初始化一个互斥锁(互斥量)–>初值可看做1 int pthread_mutex_destroy(pthread_mutex_t *mutex); //销毁锁 int pthread_mutex_lock 参数2:互斥属性。是一个传入参数,通常传NULL,选用默认属性(线程间共享). 静态初始化:如果互斥锁mutex是静态分配的(定义在全局,或加了static关键字修饰),可以直接使用宏进行初始化。 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 动态初始化:局部变量应采用动态初始化。 条件变量原语 //初始化条件变量: //本人还是喜欢静态初始化,省事儿 pthread_cont_t cont = PTHREAD_COND_INITIALIZER; //好,再看看动态初始化 int 但是互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。
代金券、腾讯视频VIP、QQ音乐VIP、QB、公仔等奖励等你来拿!
pthread_cond_t 类型的变量也可以用 PTHREAD_COND_INITIALIZER常量进行静态初始化。 pthread_cond_wait 函数返回前,自动重新对互斥量加锁(如同执行了 pthread_lock_mutex)。 互斥量的解锁和在条件变量上挂起都是自动进行的。 pthread_cond_timedwait 和 pthread_cond_wait一样,自动解锁互斥量及等待条件变量,但它还限定了等待时间。 LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。 LOCK_UN 解除文件锁定状态。 LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。 但我们可能不希望它们这样做,因为这时主进程还没准备好,和它们一起配合的其它线程还没准备好,我们希望它们在回调函数中申请完线程空间、初始化后停下来,一起等待主进程释放一个“开始”信号,然后所有线程再开始执行业务逻辑代码
互斥量 pthread提供了互斥量来确保同一时间只有一个线程访问数据。互斥量在本质上讲就是一把锁,在访问共享资源之前加锁,之后解锁。pthread下的互斥量是由pthread_mutex_t来定义。 在使用互斥量之前,必须初始化它。可以选择静态初始化为: PTHREAD_MUTEX_INITALIZER,也可以通过pthread_mutex_init()函数来初始化。 当然如果动态分配互斥量,那么在释放内存之前,需要调用pthread_mutex_destory(),这个函数不是释放内存的,是反向初始化的。 const pthread_mutexattr_t *__mutexattr); int pthread_mutex_destroy (pthread_mutex_t *__mutex); 需要使用默认属性初始化互斥量时 使用互斥量的时候注意要初始化(而初始化对应这个destroy操作),所以这两个操作是必备的。并且初始化互斥量是在创建子线程之前。
() 来初始化变量 在访问共享变量之前, 调用 pthread_mutex_lock() 获得互斥锁, 如果互斥锁被其他线程占用, 该线程会处于等待状态 访问完共享变量之后, 调用 pthread_mutex_unlock 创建互斥锁有两种方式: 静态方式和动态方式. 静态方式是使用宏 PTHREAD_MUTEX_INITIALIZER 来初始化锁, 如下所示: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 动态方式是调用 : 使用 lock 和 unlock 一个互斥锁时, 一定要先初始化该互斥锁 释放互斥锁的线程必须是获得互斥锁的那个线程 当 destroy 互斥锁的时候, 不该有线程还在使用这个互斥锁 属性 在动态创建互斥锁时 条件变量主要使用下面几个函数 初始化(init) 和互斥锁一样, 条件变量也有两种初始化方式: 静态方式和动态方式 // 静态 pthread_cond_t cond = PTHREAD_COND_INITIALIZER
delay; void main ( void ){ pthread_t reader; /* 定义延迟时间*/ delay.tv_sec = 2; delay.tv_nec = 0; /* 用默认属性初始化一个互斥锁对象 4.3 条件变量 前一节中我们讲述了如何使用互斥锁来实现线程间数据的共享和通信,互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。 而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。 注意初始化条件变量只有未被使用时才能重新初始化或被释放。释放一个条件变量的函数为pthread_cond_ destroy(pthread_cond_t cond)。 函数sem_init()用来初始化一个信号量。
终止当前线程 pthread_cancel():中断另外一个线程的运行 pthread_join():阻塞当前的线程,直到另外一个线程运行结束 pthread_attr_init():初始化线程的属性 () 初始化互斥锁 pthread_mutex_destroy() 删除互斥锁 pthread_mutex_lock():占有互斥锁(阻塞操作) pthread_mutex_trylock ():试图占有互斥锁(不阻塞操作)。 当互斥锁空闲时将占有该锁;否则立即返回 pthread_mutex_unlock(): 释放互斥锁 pthread_cond_init():初始化条件变量 pthread_cond_destroy char **argv) { printf("counter: %d/n", counter); pthread_t thd1, thd2; int ret; //初始化
// 声明一个互斥量 pthread_mutex_t mtx; // 初始化 pthread_mutex_init(&mtx, NULL); // 加锁 pthread_mutex_lock(&mtx) pthread_mutexattr_t mtx_attr; // 初始化互斥量的属性变量 pthread_mutexattr_init(&mtx_attr); // 设置递归互斥量的属性 pthread_mutexattr_settype 对于pthread: // 声明一个互斥量 pthread_mutex_t mtx; // 声明一个条件变量 pthread_cond_t cond; ... // 初始化 pthread_mutex_init 用数组实现环形队列,避免vector等动态扩张的数据结构,写在结尾,由于单写因而可以不加锁;读在开头,由于多读(避免重复消费)所以需要加一下锁(互斥量就行)。 多读单写的KV。 double buffer同名的概念比较多,这里指的是foreground 和 backgroud 两个buffer进行切换的『0 - 1切换』技术。比如实现动态加载(热加载)配置文件的时候。
在开发时我们习惯在创将某个实例之前先把静态成员变量初始化好,具体做法是通过静态初始化语句以及静态构造函数。 静态构造函数在 c# 是比较特殊的函数,它会在第一次访问所在类定义的其他方法、变量和属性之前执行,一般我们用它来初始化静态变量、实现单例模式以及执行其他一些需要在访问其他必要的工作。 如果静态字段初始化工作较为复杂或者是初始化开销很大的话,那么我们可以使用 Lazy 机制将初始化工作推迟在第一次访问该字段的时候再去执行。 在 C# 中比较常见的静态初始化语句是实现单例模式,开发人员可以将实例级别的构造函数设为 private ,并添加静态初始化语句并在其中调用这私有的实力构造函数。 ‘ 注意 这里有三点在开发中需要注意: 在每个类中只允许包含一个静态构造函数; 在第一次访问某个类之前,CLR 会自动调用这个类的静态构造函数; 在静态构造函数中应该避免将其中的异常传播到静态构造函数之外
//初始化一个互斥锁(互斥量)–>初值可看做1 int pthread_mutex_destroy(pthread_mutex_t *mutex); //销毁锁 int pthread_mutex_lock 参数2:互斥属性。是一个传入参数,通常传NULL,选用默认属性(线程间共享). 静态初始化:如果互斥锁mutex是静态分配的(定义在全局,或加了static关键字修饰),可以直接使用宏进行初始化。 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 动态初始化:局部变量应采用动态初始化。 条件变量往往和互斥一起使用 使用条件变量的代表性顺序如下: 条件变量原语 //初始化条件变量: //本人还是喜欢静态初始化,省事儿 pthread_cont_t cont = PTHREAD_COND_INITIALIZER ; //好,再看看动态初始化 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); //参数释义:cond
数据类型: pthread_mutex_t(使用之前,必须初始化) 常用函数: 初始化互斥锁--pthread_mutex_init 销毁互斥锁--pthread_mutex_destroy 加上互斥锁 写模式和互斥锁很像,一次只有一个线程可以访问。 数据类型: pthread_rwlock_t 常用函数: 初始化读写锁--pthread_rwlock_init 销毁读写锁--pthread_rwlock_destroy 读模式加锁--pthread_rwlock_rdlock 数据类型: pthread_spinlock_t 常用函数: 初始化自旋锁--pthread_spin_init 销毁自旋锁--pthread_spin_destroy 自旋锁加锁--pthread_spin_lock 数据类型: pthread_cond_t 常用函数: 初始化条件变量--pthread_cond_init 销毁条件变量--pthread_cond_destroy 用条件变量阻塞当前线程,直到条件成立
第一部分:pthread 的使用、其他相关方法。 第二部分:NSThread 的使用、线程相关用法、线程状态控制方法、线程之间的通信、线程安全和线程同步,以及线程的状态转换相关知识。 pthread_exit() 终止当前线程 pthread_cancel() 中断另外一个线程的运行 pthread_join() 阻塞当前的线程,直到另外一个线程运行结束 pthread_attr_init() 初始化线程的属性 2.5.1 NSThread 非线程安全 先来看看不考虑线程安全的代码: /** * 初始化火车票数量、卖票窗口(非线程安全)、并开始卖票 */ - (void)initTicketStatusNotSave 考虑线程安全的代码: /** * 初始化火车票数量、卖票窗口(线程安全)、并开始卖票 */ - (void)initTicketStatusSave { // 1. 线程安全) */ - (void)saleTicketSafe { while (1) { // 互斥锁 @synchronized (self) {
5.主线程执行了exec类函数,该进程的所有的地址空间完全被新程序替换,子线程退出 线程的状态 线程pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态 若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。pthread的状态在创建线程的时候指定,创建一个线程默认的状态是joinable。 (&mutex); } int main(void) { //2.初始化互斥量, 默认属性 pthread_mutex_init(&mutex, NULL); //1.启动一个线程 */ void init(struct producons *prod) { pthread_mutex_init(&prod->lock,NULL); //初始化互斥锁 pthread_cond_init (&prod->nottempty,NULL); //初始化条件变量 pthread_cond_init(&prod->notfull,NULL); //初始化条件变量 prod
GIL利用条件机制和互斥锁 <cond,mutex>保护一个锁变量 locked作为实现。 pthread_mutex_t #define PyCOND_T pthread_cond_t create_gil函数初始化锁变量 mutex和初始化条件变量 cond之后,通过 _Py_atomic_store_relaxed 等待的时候线程就会挂起,释放mutex互斥锁。cond信号被唤醒时,mutex互斥锁会自动加锁。while语句避免了意外唤醒时条件不满足,大多数情况下都是条件满足被唤醒。 ) 下 PyThread__init_thread会根据编译器和平台来确认是否要进行初始化动作,定义在 Python/thread_pthread.h: static void PyThread__init_thread id,并初始化线程状态对象。
在Java中,有两种初始化块:静态初始化块和非静态初始化块。它们都是定义在类中,用大括号{}括起来,静态代码块在大括号外还要加上static关键字。 非静态初始化块(构造代码块): 作用:给对象进行初始化。对象一建立就运行,且优先于构造函数的运行。 与构造函数的区别:非静态初始化块给所有对象进行统一初始化,构造函数只给对应对象初始化。 构造函数、非静态初始化块、静态代码块都是用于初始化,三者的执行顺序依次是:静态代码块>构造代码块>构造函数。 静态初始化块的作用就是当JVM在装载类时,你想让它做一些事情,那么,就可以用静态初始化块。 执行顺序 所有的静态初始化块都优先执行,其次才是非静态的初始化块和构造函数,它们的执行顺序是: 父类的静态初始化块 子类的静态初始化块 父类的初始化块 父类的构造函数 子类的初始化块 子类的构造函数
5.2.2 互斥锁API简述 初始化互斥锁 #include <pthread.h> int pthread_mutex_init(phtread_mutex_t *mutex, const pthread_mutexattr_t *restrict attr); 成功:返回0 该函数作用为初始化一个互斥锁,一般情况申请一个全局的pthread_mutex_t类型的互斥锁变量,通过此函数完成锁内的初始化,第一个函数将该变量的地址传入 当函数成功后会返回0,代表初始化互斥锁成功。 当然初始化互斥锁也可以调用宏来快速初始化: pthread_mutex_t mutex = PTHREAD_MUTEX_INITALIZER; 互斥锁加锁(阻塞)/解锁 #include <pthread.h 35 int main() 36 { 37 int ret; 38 pthread_t tid1,tid2; 39 ret = pthread_mutex_init(&mutex,NULL);//初始化互斥锁
则线程启动后为挂起状态。 ,那么调用者可以向它发送初始化、退出、执行某种特定的处理等消息,让它在后 台完成。 互斥与Cmutex类的对象 相对应,使用互斥对象时,必须创建一个CSingleLock或CMultiLock对象,用于实际的访问控 制,因为这里的例子只处理单个互斥,所以我们可以使用CSingleLock 对象,该对象的Lock() 函数用于占有互斥,Unlock()用于释放互斥。 long[iDataLen]; memcpy(data5, data, iDataLen << 2); unsigned long TID1, TID2, TID3, TID4; //对信号量进行初始化
:该算法是把处理机分配给就绪队列中优先权最高的进程,又分静态优先和动态优先,静态优先:进程的优先级在创建时确定(系统的进程>用户,申请资源少的>多的),优先级确定了就不变了,动态优先:创建时先确定一个优先级 ,随着执行时间变化,动态调整(Unix系统会根据进程占用CPU的时间或等待CPU时间) 时间片轮转法:轮流的调度就绪队列中的所有进程。 6、全局变量、静态变量 五、死锁 一组进程在执行过程中,每个进程都在等待其他进程所占有的资源而造成了互相等待,此时系统产生了死锁 1、四个必要条件: (1)互斥条件:每个资源都是不可共享的 (2)请求保持条件 /** * 使用__cond_attr初始化条件变量,__cond_attr设置为NULL,将使用默认属性初始化条件变量。 * @param __cond 要初始化的条件变量 * @param __cond_attr 属性 * @return 如果成功返回0,失败返回错误码 */ int pthread_cond_init
我们用上面说的这些知识来实现这样一个功能: ---- 有一int型全局变量g_Flag初始值为0; 在主线称中起动线程1,打印“this is thread1”,并将g_Flag设置为1 在主线称中启动线程 /a.out 注意编译命令之后的-lpthread参数是必须的,否则创建线程可能失败,主要原因是: pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用 条件变量始终与互斥锁一起使用。对条件的测试是在互斥锁(互斥)的保护下进行的。 如果条件为假,线程通常会基于条件变量阻塞,并以原子方式释放等待条件变化的互斥锁。 为什么条件变量始终与互斥锁一起使用,对条件的测试是在互斥锁(互斥)的保护下进行的呢?因为“某个特性条件”通常是在多个线程之间共享的某个变量。互斥锁允许这个变量可以在不同的线程中设置和检测。 如熟悉,编写程序完成如下功能: 1)有一int型全局变量g_Flag初始值为0; 2)在主线称中起动线程1,打印“this is thread1”,并将g_Flag设置为1 3)在主线称中启动线程
注意: 这里在Linux系统下编写线程程序时,使用gcc编译时,一定要在gcc编译语句后面加上"-lpthread"(如上面演示为例,这里加了一个-lpthread,表示要找到这个动态链接库来 在这个过程中,任务分发器向任务队列中追加任务和工作线程取出任务的时候,都需要使用互斥锁对任务队列进行保护(不过这里还没设计到互斥锁的概念,你可以把互斥锁看成你平常开门和关门的动作执行就可以了,这样就很容易理解了 参数说明: 其中sem是要初始化的信号量,pshared表示此信号量是在进程间共享还是线程间共享,value是信号量的初始值。 只有用sem_init初始化的信号量才能用sem_destroy销毁。 int main(void) { int ret = -1; pthread_t th = -1; sem_init(&sem, 0, 0); //信号量初始化
云开发Web应用托管(TCBH)为您的Web应用提供一站式托管服务,支持包括静态网站、动态Web服务、容器化服务以及后台微服务等各种类型的Web应用,提供默认域名、自定义域名、HTTPS、CDN加速,提升web应用的性能和安全性,此外还提供基于Git工作流、DevOps流程、加速开发部署流程,提供极佳的体验。
扫码关注云+社区
领取腾讯云代金券