精华内容
下载资源
问答
  • 是标识加互斥锁还是共享锁. 当为  True  时, 即  for share  的语句, 是共享锁. 多个事务可以获取共享锁, 互斥锁只能一个事务获取. 有"多个地方"都希望是"这段时间我获取的数据不能被修改, 我也不会改", 那么...

    关于sqlalchemy,可以细度这个网址:http://www.codexiu.cn/python/SQLAlchemy%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/73/531/

     

    5.2. for update

    SQLAlchemy 的 Query 支持 select ... for update / share .

    session.Query(User).with_for_update().first()
    session.Query(User).with_for_update(read=True).first()

    完整形式是:

    with_for_update(read=False, nowait=False, of=None)
    read
    是标识加互斥锁还是共享锁. 当为  True 时, 即  for share 的语句, 是共享锁. 多个事务可以获取共享锁, 互斥锁只能一个事务获取. 有"多个地方"都希望是"这段时间我获取的数据不能被修改, 我也不会改", 那么只能使用共享锁.
    nowait
    其它事务碰到锁, 是否不等待直接"报错".
    of
    指明上锁的表, 如果不指明, 则查询中涉及的所有表(行)都会加锁.

     

     

    SELECT ... FOR UPDATE 的用法。由于InnoDB 预设是Row-Level Lock,所以只有「明确」的指定主键或者其他索引的键,MySQL 才会执行Row lock ( 只锁住被选取的数据) ,否则mysql 将会执行Table Lock (将整个数据表单给锁住)。
    只锁住被选取的数据的好处是:多线程时,如果其他线程使用的是非锁住的数据,则不会受影响,无需等待解锁,更好的实现了并发。


     

    参考:

    http://www.codexiu.cn/python/SQLAlchemy%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/531/

    https://www.jianshu.com/p/7e4de9ab942c

    展开全文
  • 使用互斥锁和共享内存实现的非阻塞FIFO,另外代码中有包含信号量的实现。个人测试稳定,有一些注释,一起学习。如有问题,欢迎讨论。
  • 该博客已经搬迁,请移步到这里

      该博客已经搬迁,请移步到这里

    展开全文
  • 02 进程间的互斥锁和线程间互斥锁的区别 函数pthread_mutex_init(互斥锁地址, 属性对象地址)在定义一把线程锁的时候第二个参数通常传为NULL,这样该锁默认只能被统一进程下的线程持有。 如果要将其定义为进程之间...

    01 原理

    开辟一块共享内存,使得相关进程均可访问同一块区域,再将互斥锁定义在该区域(即共享内存)上,使得相关进程可以使用该锁。

    02 进程间的互斥锁和线程间互斥锁的区别

    函数pthread_mutex_init(互斥锁地址, 属性对象地址)在定义一把线程锁的时候第二个参数通常传为NULL,这样该锁默认只能被统一进程下的线程持有。

    如果要将其定义为进程之间可以持有的互斥锁,则需要传入属性对象地址。

    // 锁
    pthread_mutex_t lock;
    // 状态对象
    pthread_mutexattr_t lock_attr;
    
    // 初始化锁状态,设置状态状态为——进程共享
    pthread_mutexattr_init(&lock_attr);
    pthread_mutexattr_setpshared(&lock_attr, PTHREAD_PROCESS_SHARED);
    // 用锁状态来初始化锁
    pthread_mutex_init(&lock, &lock_attr);
    
    // 使用时不牵扯状态对象,但状态对象在锁销毁时也要销毁
    pthread_mutex_lock(&lock);
    pthread_mutex_unlock(&lock);
    
    // 销毁锁和锁状态
    pthread_mutex_destroy(&lock);
    pthread_mutexattr_destroy(&lock_attr);
    

    现在我们需要将其定义在共享内存上,这样该锁就可以被其他进程访问,否则不能达到效果,原因请参考Linux虚拟地址

    03 将锁定义在共享内存上

    共享内存的开辟参考Linux共享内存

    04 Show me the code

    父进程每次将共享内存上的变量加1,子进程每次将其加2,用定义在共享内存上的互斥锁维护该变量的累加操作原子性。

    去掉两进程加锁、开锁的过程则结果出错(N越大越容易暴露问题)。

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <assert.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    /**
     *  返回一片共享内存标识符,用于后续获取该共享内存,以及销毁该共享内存
     *  INDEX_OF_KEY —— 自定义的该共享内存序号
     *  LENGTH —— 共享内存大小
     */
    const int create_flag(const int INDEX_OF_KEY, const unsigned int LENGTH) {
        // 生成key
        const char* FILE_PATH = "./";
        key_t key = ftok(FILE_PATH, INDEX_OF_KEY);
    
        // 创建共享内存空间
        const int FLAG = shmget(key, LENGTH, IPC_CREAT | 0666);
    
        return FLAG;
    }
    
    
    // 定义进程锁结构体
    typedef struct MUTEX_PACKAGE {
        // 锁以及状态
        pthread_mutex_t lock;
        pthread_mutexattr_t lock_attr;
        // 在共享内存中的标识符
        int FLAG;
    } mutex_package_t;
    
    
    // 初始化进程锁结构体
    const int init(void* pthis) {
        mutex_package_t* mp = (mutex_package_t*)pthis;
        // 初始化锁状态,设置状态状态为——进程共享
        pthread_mutexattr_init(&(mp->lock_attr));
        pthread_mutexattr_setpshared(&(mp->lock_attr), PTHREAD_PROCESS_SHARED);
        // 用锁状态来初始化锁
        pthread_mutex_init(&(mp->lock), &(mp->lock_attr));
    
        return 0;
    }
    
    
    // 在共享内存上定义进程锁结构体并且返回其位置
    mutex_package_t* create_mutex_package(const int INDEX) {
        const int FLAG = create_flag(INDEX, sizeof(mutex_package_t));
        mutex_package_t* mp = (mutex_package_t*)shmat(FLAG, NULL, SHM_R | SHM_W);
        mp->FLAG = FLAG;
    
        assert(init(mp) == 0);
    
        return mp;
    }
    
    
    // 销毁进程锁结构体,利用其FLAG变量索引到其占用的共享内存并销毁
    const int destory_mutex_package(mutex_package_t* mp) {
        // 销毁锁和锁状态
        pthread_mutex_destroy(&(mp->lock));
        pthread_mutexattr_destroy(&(mp->lock_attr));
    
        // 释放共享内存
        assert(shmctl(mp->FLAG, IPC_RMID, NULL) == 0);
    
        return 0;
    }
    
    
    int main() {
        // 创建自定义进程锁
        mutex_package_t* mp = create_mutex_package(111);
    
        // 获取一片共享内存空间
        const int FLAG = create_flag(222, sizeof(int));
        volatile int* x = (int*)shmat(FLAG, NULL, 0);
    
        // 创建新进程
        int id = fork();
        assert(id >= 0);
    
        // 设置循环次数
        const int N = 1000000;
    
        // 父进程每次加1,子进程每次加2
        int i;
        for (i = 0; i < N; ++i) {
    
            if (id > 0) {  // 父进程
                // 加锁
                pthread_mutex_lock(&(mp->lock));
                int temp = *x;
                *x = temp+1;
                // 解锁
                pthread_mutex_unlock(&(mp->lock));
    
            } else {  // 子进程
                // 加锁
                pthread_mutex_lock(&(mp->lock));
                int temp = *x;
                *x = temp+2;
                // 解锁
                pthread_mutex_unlock(&(mp->lock));
            }
    
        }
    
        // 等待循环完毕
        sleep(1);
    
        // 打印
        printf("pid= %d, x_address= %x, x= %d\n", getpid(), x, *x);
    
        // 等待打印完毕
        sleep(1);
    
        // 销毁进程锁,释放申请的共享内存
        if (id > 0) {  // 父进程
            destory_mutex_package(mp);
            mp = NULL;
            shmctl(FLAG, IPC_RMID, NULL);
            x = NULL;
            printf("父进程释放资源完毕\n");
        }
    
        return 0;
    }
    

    05 结果

    pid= 64735, x_address= c1f1000, x= 3000000
    pid= 64737, x_address= c1f1000, x= 3000000
    父进程释放资源完毕

    展开全文
  • MySQL:共享锁 互斥锁 意向锁。

    千次阅读 2019-12-16 14:01:43
    MySQL:共享锁 互斥锁 意向锁。

    经常听到数据库的锁机制,不同的数据库的不同实现不同, 听多了就头疼了,今天就把MySQL的锁整的明明白白:

    首先想一下为什么我们会需要锁,其实就是为了解决并发操作数据的,是一种控制并发的机制。

    乐观锁和悲观锁

    乐观锁和悲观锁其实是两种思想,用来指导实现锁的功能的不同实现思想,

    • 乐观锁是一种思想,它其实并不是一种真正的『锁』,它会先尝试对资源进行修改,在写回时判断资源是否进行了改变,如果没有发生改变就会写回,否则就会进行重试,在整个的执行过程中其实都没有对数据库进行加锁;
    • 悲观锁就是一种真正的锁了,它会在获取资源前对资源进行加锁,确保同一时刻只有有限的线程能够访问该资源,其他想要尝试获取资源的操作都会进入等待状态,直到该线程完成了对资源的操作并且释放了锁后,其他线程才能重新操作资源;

    在这两种指导思想下产生了对应的锁:

    乐观锁的实现

    我们可以对一行数据创建一个字段专门用来存放对这行数据操作时的时间戳,比如我们第一次读取的时候拿到时间戳 timestamep=111,a=2, id =1 ,然后提交a=3更新的时候,我们的update  tablename set a = 3  where id =1 timestamp=111 失败,说明这条数据被别的事务操作了。

    乐观锁是一种软并发控制,需要你设置好完整的逻辑处理。

    悲观锁的实现

    悲观锁也就是我们经常说的锁的概念,包括什么共享锁,互斥锁,读锁,写锁,意向共享锁,意向互斥锁,共享锁和读锁是一个概念,互斥锁和写锁一个概念,以此类推 意向共享锁也可以叫意向读锁, 意向互斥锁也可以叫意向写锁。

    这些锁的使用使用在哪里是有锁的使用范围的,也就是每种锁的粒度。MySQL的锁的粒度和引擎相关,我们今天就着重介绍一下InnoDB,因为这个是5.5.8版本以后的默认版本。

    注意:MySQL的引擎是表级别的,就是在创建表的时候指定,也就是说你一个数据库的不同表你可以指定不同引擎

    • MySQL的锁的粒度有:行级锁 和 表级锁。
    • MySQL的锁的作用:共享锁(读锁) 和 互斥锁(写锁)---------行级锁。
    • MySQL的意向锁是表级锁,

    意向锁

    • 意向共享锁:事务想要在获得表中某些记录的共享锁,需要在表上先加意向共享锁;
    • 意向互斥锁:事务想要在获得表中某些记录的互斥锁,需要在表上先加意向互斥锁;

    意向锁其实不会阻塞全表扫描之外的任何请求,它们的主要目的是为了表示是否有人请求锁定表中的某一行数据。

    有的人可能会对意向锁的目的并不是完全的理解,我们在这里可以举一个例子:如果没有意向锁,当已经有人使用行锁对表中的某一行进行修改时,如果另外一个请求要对全表进行修改,那么就需要对所有的行是否被锁定进行扫描,在这种情况下,效率是非常低的;不过,在引入意向锁之后,当有人使用行锁对表中的某一行进行修改之前,会先为表添加意向互斥锁(IX),再为行记录添加互斥锁(X),在这时如果有人尝试对全表进行修改就不需要判断表中的每一行数据是否被加锁了,只需要通过等待意向互斥锁被释放就可以了。

    各种锁之间的约束关系:

    展开全文
  • 共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,直到已释放所有共享锁。获准共享锁的事务只能读数据,不能修改数据。 排他锁:如果事务T对数据A加上排他锁后,则其他事务不能...
  • 经常听到数据库的锁机制,不同的数据库... 乐观锁和悲观锁其实是两种思想,用来指导实现锁的功能的不同实现思想, 乐观锁是一种思想,它其实并不是一种真正的『锁』,它会先尝试对资源进行修改,在写回时判断资源是...
  • 线程数据共享我们把上篇博客线程代码拿过来from threading import Thread,Lock import time n=100def task(): global n mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release()if __name__ == ...
  • 在多任务环境下,往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。互斥锁(mutex)又称互斥型信号量,是一种特殊的二值信号量,用于实现对共享资源的独占式处理。...
  • 互斥锁

    2019-10-23 10:59:17
    互斥锁是一个二元变量,其状态为开锁(允许0)上锁(禁止1),将某个共享资源与某个特定互斥锁在逻辑上绑定(要申请该资源必须先获取锁)。 (1)访问公共资源前,必须申请该互斥锁,若处于开锁状态,则申请到锁对象,并...
  • 添加互斥锁2添加递归互斥锁三.互斥锁1.代码2.测试四.递归互斥锁1.代码2.测试 FreeRTOS系统 一.简绍 互斥锁,谁获得的消息谁来释放 递归互斥锁,可以连续获得两次,同时释放的时候也释放两次 二.STM32CubMx配置 1....
  • 共享锁 互斥锁 自旋锁

    千次阅读 2013-04-17 23:17:29
    共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,直到已释放所有共享锁。获准共享锁的事务只能读数据,不能修改数据。 排他锁:如果事务T对数据A加上排他锁后,则其他事务...
  • 独占锁(写锁)/共享锁(读锁)/互斥锁 独占锁:指该锁一次只能被一个线程所持有。对ReentrantLockSynchronized而言都是独占锁。 共享锁:指该锁可被多个线程所持有。 对ReentrantReadWriteLock其读锁是共享锁,其...
  • golang互斥锁和读写锁性能分析

    千次阅读 2019-04-05 21:42:20
    在并发操作中为了防止多任务同时修改共享资源导致的不确定结果,我们可能会用到互斥锁和读写锁。 一:互斥锁 1.互斥锁有两种操作,获取锁和释放锁 2.当有一个goroutine获取了互斥锁后,任何goroutine都不可以获取...
  • 1.什么是互斥锁 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。线程同步能够保证多个线程安全访问竞争资源,最简单的同步,是引入互斥锁互斥锁为资源引入一个状态:锁定/非锁定 某个线程要...
  • 1、Java读写锁理论 ...对ReentrantReadWriteLock而言,其读锁是共享锁,其写锁是独占锁。读锁的共享性可保证并发读是非常高效的,读写、写读、写写的过程都是互斥的。 2、Java读写锁代码验证 Demo One:代...
  • 互斥锁和自旋锁在内核中使用的比较频繁,但是具体情况下怎么选择它们。 有如下选用原则: 1、当锁不能被获取到时,
  • C共享互斥锁

    2018-12-26 22:20:20
    C共享互斥锁 C普通锁 当一个地方加上锁后,其他所有想获取锁的都会阻塞 基础使用 `pthread_mutex_t mutex;` `struct timespec time;` `localtime(&amp;time)/*使用绝对时间*/` `mutex = PTHREAD_MUTEX_...
  • linux互斥锁和PV原语

    千次阅读 2017-08-11 11:01:08
    刚接触linux互斥锁的时候可能会比较抽象,所以本文想要用PV原语来更加具体的理解linux互斥锁。如若有误,烦请指出,不甚感激!由于线程共享了进程的资源地址空间,因此,任何线程对系统资源的操作都会给其他线程...
  • SharedExclusiveLock 共享互斥锁

    千次阅读 2017-04-18 15:20:12
    共享互斥锁,有时也被称为单写多读锁。 简单点的应用场景就是:一个写多个读。代码来源是webrtc的SharedExclusiveLock类// This class provides shared-exclusive lock. It can be used in cases like // multiple-...
  • 互斥锁死锁

    2019-04-26 18:53:10
    有时,一个线程可能会同时访问多个不同的共享资源,而每个共享资源都需要有不同互斥锁管理。那么程序编写在不经意间极容易造成死锁的情况。造成死锁的原因有很多,本节将通过一些示例展示死锁的情况。 (1)在互斥锁...
  • 互斥锁和条件变量锁注意事项

    千次阅读 2019-04-19 00:07:00
    互斥锁和条件变量锁注意事项 如果互斥锁变量是静态分配的,那么我们可以把它初始化成常值PTHREAD_MUTEX_INITIALIZER ...如果互斥锁是动态分配的(例如malloc new)或者分配在共享内存区中,那么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 110,829
精华内容 44,331
关键字:

互斥锁和共享锁