线程锁
线程锁及线程锁的作用
什么是线程锁机制
多线程可以同时运行多个任务但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误!
so,不使用线程锁, 可能导致错误
分布式锁、进程锁、线程锁分别是什么
在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁。
线程锁:大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。但是,其余线程是可以访问该对象中的非加锁代码块的。
进程锁:也是为了控制同一操作系统中多个进程访问一个共享资源,只是因为程序的独立性,各个进程是无法控制其他进程对资源的访问的,但是可以使用本地系统的信号量控制(操作系统基本知识)。
分布式锁:当多个进程不在同一个系统之中时,使用分布式锁控制多个进程对资源的访问。
分布式锁到底是什么,怎么实现?
intsmaze说简单点,实现分布式锁必须要依靠第三方存储介质来存储锁的元数据等信息。比如分布式集群要操作某一行数据时,这个数据的流水号是唯一的,那么我们就把这个流水号作为一把锁的id,当某进程要操作该数据时,先去第三方存储介质中看该锁id是否存在,如果不存在,则将该锁id写入,然后执对该数据的操作;当其他进程要访问这个数据时,会先到第三方存储介质中查看有没有这个数据的锁id,有的话就认为这行数据目前已经有其他进程在使用了,就会不断地轮询第三方存储介质看其他进程是否释放掉该锁;当进程操作完该数据后,该进程就到第三方存储介质中把该锁id删除掉,这样其他轮询的进程就能得到对该锁的控制。
说了这么多,再补充一点,线程锁,进程锁,分布式锁的作用都是一样的,只是作用的范围大小不同。范围大小:分布式锁 > 进程锁 > 线程锁。能用线程锁,进程锁情况下使用分布式锁也是可以的,能用线程锁的情况下使用进程锁也是可以的。只是范围越大技术复杂度就越大。
用法
1 #创建锁 2 lock = threading.Lock() 3 #锁定 4 lock.acquire([timeout]) 5 #释放 6 lock.release()
优缺点
优点:保证资源同步
缺点:有等待肯定会慢
参考博客:https://www.cnblogs.com/ch94/p/10119164.html
c++线程中的几种锁
线程之间的锁有:互斥锁、条件锁、自旋锁、读写锁、递归锁。一般而言,锁的功能越强大,性能就会越低。
1、互斥锁
互斥锁用于控制多个线程对他们之间共享资源互斥访问的一个信号量。也就是说是为了避免多个线程在某一时刻同时操作一个共享资源。例如线程池中的有多个空闲线程和一个任务队列。任何是一个线程都要使用互斥锁互斥访问任务队列,以避免多个线程同时访问任务队列以发生错乱。
在某一时刻,只有一个线程可以获取互斥锁,在释放互斥锁之前其他线程都不能获取该互斥锁。如果其他线程想要获取这个互斥锁,那么这个线程只能以阻塞方式进行等待。
<pthread.h> //头文件 // pthread_mutex_t//类型: //函数:pthread_mutex_init(pthread_mutex_t * mutex, const phtread_mutexattr_t * mutexattr);//动态方式创建锁,相当于new动态创建一个对象 pthread_mutex_destory(pthread_mutex_t *mutex)//释放互斥锁,相当于delete pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//以静态方式创建锁 pthread_mutex_lock(pthread_mutex_t *mutex)//以阻塞方式运行的。如果之前mutex被加锁了,那么程序会阻塞在这里。 pthread_mutex_unlock(pthread_mutex_t *mutex) int pthread_mutex_trylock(pthread_mutex_t * mutex);//会尝试对mutex加锁。如果mutex之前已经被锁定,返回非0,;如果mutex没有被锁定,则函数返回并锁定mutex //该函数是以非阻塞方式运行了。也就是说如果mutex之前已经被锁定,函数会返回非0,程序继续往下执行。
参考博客:https://www.cnblogs.com/steamedbun/p/9376458.html
对于普通的加锁解锁操作,使用lock、unlock就够用了。但如果分支太多,这个就不好控制了。C++11提供了一种自动锁的机制,比如上面代码可以替换成这样:
1 void icrement () { 2 3 for (int i = 0; i < 100000000; i++) { 4 5 //调用即加锁,离开大括号作用域自动解锁 6 7 lock_guard<mutex> lock (mut); 8 9 val++; 10 11 } 12 13 }
自动锁就不用刻意的解锁了,对于多分支的情况相当方便。
参考博客:https://blog.csdn.net/xionglifei2014/article/details/82423292