葡京网投哪个正规 > 联系我们 > 【葡京网投哪个正规】动手实现读写锁,java并发编程

原标题:【葡京网投哪个正规】动手实现读写锁,java并发编程

浏览次数:85 时间:2020-05-08

Insert、Update和DeleteSQLServer里3个写操作是INSERT、UPDATE和DELETE。如果加上约束、触发器和外键,写操作可以变得更复杂。这里仅关心基本的写操作。对于3个操作中的每一个,对于堆表和有聚集索引的表来说都有不同的图标,如图2-31、2-32和2-33所示。<

排他锁的弊端

 前提:

python操作excel需要使用的模块有xlrd、xlwt、xlutils。对excel进行读、写、更新操作。操作excel时需要先导入这些模块,demo如下:

最近项目中需要用到读写锁

     在多个线程之间共享数据,普遍做法是加锁读写,也就是同一个时刻只有一个线程能够读或者写,以保证数据一致性,即线程安全。例如下面的伪代码是常见的做法

excel-读操作知识点:

 1 import xlrd
 2 '''
 3 读取 excel的操作步骤如下:
 4 1. 打开excel,打开的excel必须存在
 5 2. 获取sheet对象
 6 3. 对excel进行操作:
 7     获取excel的总行数、总列数、读取excel每一行的数据、读取excel每一列的数据、获取某个单元格的值
 8 '''
 9 #打开excel,打开的excel必须存在,返回book对象
10 book = xlrd.open_workbook('students.xlsx')
11 #通过索引获取sheet对象
12 sheet = book.sheet_by_index(0)
13 #有多个sheet页时可以通过sheet的名称来获取sheet对象
14 sheet1 = book.sheet_by_name('Sheet1')
15 
16 #获取excel的总行数,
17 rows = sheet.nrows
18 #获取excel的总列数
19 cols = sheet.ncols
20 #获取excel第2行的数据,返回结果为list:[2.0, 'b', 'women']
21 row_value = sheet.row_values(2)
22 #获取excel第1列的数据,返回结果为list:['name', 'a', 'b', 'c', 'd', 'e', 'f', 'g', '小白', '小黑']
23 col_values = sheet.col_values(1)
24 #获取单元格第8行第1列的数据,返回结果为text: text:'小白'
25 cell_value = sheet.cell(8, 1)
26 #将text类型的结果转换为str类型:小白
27 cell_str = sheet.cell(8, 1).value
注意:获取每行、每列、某个单元格的值时,注意行、列的值要存在,否则会报错:list index out of range

读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说 读-读能共存,读-写不能共存,写-写不能共存

 1 void Read()
 2 {
 3     Lock(mutex);
 4 
 5     // 读取数据
 6 
 7     UnLock(mutex);
 8 }
 9 
10 void Write()
11 {
12     Lock(mutex);
13 
14     // 写入数据
15 
16     UnLock(mutex);
17 }
excel - 读取excel小案例:
 1 import xlrd
 2 '''
 3 读取excel的数据,读取数据的列固定,循环读取每行数据,读取后的数据格式如下:
 4 [
 5 {'name':xxx,'sex':xxx,'id':1},
 6 {'name':xxx,'sex':xxx,'id':1},
 7 .......
 8 ]
 9 '''
10 def readExcel():
11     try:
12         #若输入的excel不存在,则打开excel报错
13         book = xlrd.open_workbook('students.xlsx')
14     except Exception as e:
15         print('error msg:', e)
16     else:
17         sheet = book.sheet_by_index(0)
18         #获取excel的总行数
19         rows = sheet.nrows
20         stu_list = []
21         #循环读取每行数据,第0行是表头信息,所以从第1行读取数据
22         for row in range(1, rows):
23             stu = {}
24             #获取第row行的第0列所有数据
25             id = sheet.cell(row, 0).value
26             name = sheet.cell(row, 1).value
27             sex = sheet.cell(row, 2).value
28             #将id、name、sex添加到字典,若元素不存在则新增,否则是更新操作
29             stu['id'] = id
30             stu['name'] = name
31             stu['sex'] = sex
32             stu_list.append(stu)
33         print(stu_list)
34 
35 if __name__ == '__main__':
36     readExcel()

excel数据格式如下:

葡京正网网投 1

 

 

 excel - 写操作知识点:

 1 import xlwt
 2 '''
 3 写 excel的操作步骤如下:
 4 1. 打开excel,打开不存在的excel,若打开已存在的excel,进行写操作,写入的数据会覆盖以前的数据
 5 2. 获取sheet对象并指定sheet的名称
 6 3. 对excel进行操作:
 7     写入excel、保存excel
 8 '''
 9 #打开excel创建book对象
10 book = xlwt.Workbook()
11 #创建sheet指定sheet名称
12 sheet = book.add_sheet('stu2')
13 #写入excel数据,第n行第n列写入某个值,写入的数据类型为str
14 sheet.write(0, 0, '编号')
15 sheet.write(0, 1, '姓名')
16 sheet.write(0, 2, '年龄')
17 #保存excel,保存的后缀必须是xls
18 book.save('studet.xls')

excel写入 新的excel后,数据格式如下:

葡京正网网投 2

excel操作 已存在的excel,进行写操作后的 excel格式如下:

葡京正网网投 3 ----> 葡京正网网投 4

我们直接使用java的读写锁  ReadWriteLock

读写锁的设计

excel - 写excel小案例:
 1 import xlwt
 2 '''
 3 将list数据:
 4 [{'name': '小白', 'id': 1.0, 'sex': '男'},
 5     {'name': '小花', 'id': 2.0, 'sex': '女'},
 6     {'name': '小黑', 'id': 3.0, 'sex': '男'},
 7      {'name': '小茹', 'id': 4.0, 'sex': '女'},
 8       {'name': '小小', 'id': 5.0, 'sex': '男'}]
 9 写入excel,title信息为:编号、姓名、性别
10 '''
11 def writeExcel():
12     book = xlwt.Workbook()
13     sheet = book.add_sheet('stu')
14     titles = ['编号', '姓名', '性别']
15     #循环读取titles的长度,col的值为:0,1,2,并将title值写入excel
16     for title_col in range(len(titles)):
17         #title 写入excel的第0行的第col列,写入titles[col]值
18         sheet.write(0, title_col, titles[title_col])
19     students_list = [{'name': '小白', 'id': 1.0, 'sex': '男'},{'name': '小花', 'id': 2.0, 'sex': '女'},{'name': '小黑', 'id': 3.0, 'sex': '男'},{'name': '小茹', 'id': 4.0, 'sex': '女'},{'name': '小小', 'id': 5.0, 'sex': '男'}]
20     for stu_row in range(len(students_list)):
21         #循环读取student_list的长度,从0开始,写入excel时从第1行开始写入数据
22         #写入excel的数据是从list里进行取值,获取list的每个元素,返回字典,然后通过字典的key获取value
23         sheet.write(stu_row+1, 0, students_list[stu_row]['id'])
24         sheet.write(stu_row+1, 1, students_list[stu_row]['name'])
25         sheet.write(stu_row+1, 2, students_list[stu_row]['sex'])
26     book.save('student.xls')
27 if __name__ == '__main__':
28     writeExcel()

excel数据格式如下:

葡京正网网投 5

如下代码是使用缓存的典型场景:

     这样的锁是具有排他性的,会在一定程度上影响程序的效率。假设有多个线程竞争获得读写权利,显然同一个时刻只有一个线程能够获得,要么进行读操作,要么进行写操作,而且,在读操作和读操作之间,或在写操作和写操作之间,同样具有排他性,存在下面的关系

 excel- 更新操作知识点:

 1 import xlrd
 2 from xlutils.copy import copy
 3 '''
 4 更新excel操作:
 5 1. 打开excel,更新的excel必须存在
 6 2. 复制一个新的excel,使用xlutils模块中的copy方法
 7 3. 更新excel内的数据
 8 4. 保存更新后的excel数据,以前的excel数据不会更改
 9 '''
10 from xlutils.copy import copy
11 #打开excel
12 book = xlrd.open_workbook('student.xlsx')
13 #复制一个新的excel
14 new_book = copy(book)
15 #查看某个对象下的所有方法
16 #print(dir(new_book))
17 #获取新excel的sheet对象
18 sheet = new_book.get_sheet(0)
19 #新增一列数据
20 sheet.write(0, 3, '更新')
21 #更新第4行第1列的值,将其修改为'郭静',修改的数据类型为str
22 sheet.write(4, 1, '郭静')
23 #保存更改后的excel,以前的excel数据不更改
24 new_book.save('student.xls')

 以上为excel简单操作~~~~

public class ReadWriteLockTest {

    private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private static LoadingCache<Long, LinkModel> windowCache = CacheBuilder
            .newBuilder()
            .expireAfterWrite(Config.ALL_RELOAD_CYCLE+1,TimeUnit.HOURS) //写入ALL_RELOAD_CYCLE小时后remove掉
            .build(new CacheLoader<Long, LinkModel>() {
                @Override
                public LinkModel load(Long key) throws Exception {
                    return LinkModelDAO.getLinkModelWindow(key);
                }
            });


    public static LinkModel getLinkModelWindow(long linkId) {
        try {
            readWriteLock.readLock().lock();
            LinkModel model = windowCache.get(linkId);
            return model;
        } catch (ExecutionException e) {
            LOGGER.error(e.getMessage(), e);
        }finally {
            readWriteLock.readLock().unlock();
        }
        return null;
    }


    public static  void refershModelWindowCache(String partitionId){

        try {
            readWriteLock.writeLock().lock();
            HashMap<Long, LinkModel> linkModelHashMap = LinkModelDAO.getLinkModelWindowsByPartition(partitionId,Config.ALL_ROADCLASS_LIST);
            if(MapUtils.isNotEmpty(linkModelHashMap)){
                windowCache.cleanUp();
                windowCache.putAll(linkModelHashMap);
            }
        } catch (EventMiningException e) {
            LOGGER.error(e.getMessage(), e);
        }finally {
            readWriteLock.writeLock().unlock();
        }

    }
}

1、读-写,排他

 下面这篇文章写得比较详细:

2、写-写,排他

 

3、读-读,排他

葡京正网网投,     既然排他锁影响程序效率,那么该如何优化呢?排他锁的目的,为了避免出现这样的竞争条件,在一个线程在未完成读操作之前,另一个线程写操作改变了数据,或者多个线程同时进行写操作。显然,在读操作和写操作之间,或在写操作和写操作之间,要求具有排他性,而排他锁带入到负面影响是,在读操作和读操作之间也具有了排他性。到这里,可以设想一下读写锁能够解决什么问题,没错,就是为了屏蔽这个负面影响,能够满足下面的关系

1、读-写,排他

2、写-写,排他

3、读-读,共享

     简单地说,就是多个线程能够同时进行读操作。思路如下(伪代码)

 1 void Read()
 2 {
 3     Wait(condition);
 4 
 5     Lock(mutex);
 6     if(0 == Count++)
 7         Lock(semaphore);
 8     UnLock(mutex);
 9 
10     // 读取数据
11 
12     Lock(mutex);
13     if(0 == --Count)
14         UnLock(semaphore);
15     UnLock(mutex);
16 }
17 
18 void Write()
19 {
20     Destroy(condition);
21     Lock(semaphore);
22 
23     // 写入数据
24 
25     UnLock(semaphore);
26     Create(condition);
27 }

  在代码中,信号量semaphore的初值为1,为了读-写能够排他和写-写排他这两个关系。Count记录有多少个读操作,而mutex是为了保证Count线程安全。忽略condition相关的代码,可以说,已经实现了前面提到的读写锁。但为什么加入condition呢?原因是这样的,如果有多个线程在连续进行读操作,可能导致长时间不能进行写操作,也就是通常说的写锁饥饿。condition可以解决这个问题,如果有线程正在等待写操作,那么新的读操作先等待,等到写操作完成后再开始。这样可以保证获得读写操作的机会是相对公平的。

葡京网投哪个正规,在Windows中实现读写锁

  在Windows平台,Vista和Server 2008及其更高的版本才开始提供读写锁相关的API,如果需要支持XP系统,那么往往需要自己实现读写锁机制。前面已经介绍过如何实现读写锁,这里不费口舌,直接贴出代码

葡京正网网投 6葡京正网网投 7

 1 // 实现代码
 2 
 3 class RWLock
 4 {
 5 public:
 6     RWLock();
 7     ~RWLock();
 8 public:
 9     void AcquireReadLock();
10     void ReleaseReadLock();
11     void AcquireWriteLock();
12     void ReleaseWriteLock();
13 private:
14     volatile DWORD      m_cnt;
15     CRITICAL_SECTION    m_cs;
16     HANDLE              m_evt;
17     HANDLE              m_sem;
18 };
19 
20 RWLock::RWLock()
21     : m_cnt(0)
22     , m_evt(NULL)
23     , m_cs(NULL)
24     , m_sem(NULL)
25 {
26     // 提倡的做法在专门的初始化函数里创建和初始化这些变量
27 
28     ::InitializeCriticalSection(&m_cs);
29 
30     // Event必须是手动重置,否则存在死锁隐患,即等待Event前,先被激活了
31     m_evt = ::CreateEvent(NULL, TRUE, TRUE, NULL);
32     m_sem = ::CreateSemaphore(NULL, 1, 1, NULL);
33 }
34 
35 RWLock::~RWLock()
36 {
37     ::CloseHandle(m_sem);
38     ::CloseHandle(m_evt);
39     ::DeleteCriticalSection(&m_cs);
40 }
41 
42 void RWLock::AcquireReadLock()
43 {
44     ::WaitForSingleObject(m_evt, INFINITE);
45 
46     ::EnterCriticalSection(&m_cs);
47     if(0 == m_cnt++)
48         ::WaitForSingleObject(m_sem, INFINITE);
49     ::LeaveCriticalSection(&m_cs);
50 }
51 
52 void RWLock::ReleaseReadLock()
53 {
54     ::EnterCriticalSection(&m_cs);
55     if(0 == --m_cnt)
56         ::ReleaseSemaphore(m_sem, 1, NULL);
57     ::LeaveCriticalSection(&m_cs);
58 }
59 
60 void RWLock::AcquireWriteLock()
61 {
62     ::ResetEvent(m_evt);
63     ::WaitForSingleObject(m_sem, INFINITE);
64 }
65 
66 void RWLock::ReleaseWriteLock()
67 {
68     ::ReleaseSemaphore(m_sem, 1, NULL);
69     ::SetEvent(m_evt);
70 }
71 
72 // 使用示例
73 
74 void Read()
75 {
76     // 多个线程能够同时进行读操作
77 
78     rwLock.AcquireReadLock();
79 
80     // 读取数据
81     
82     rwLock.ReleaseReadLock();
83 }
84 
85 void Write()
86 {
87     rwLock.AcquireWriteLock();
88 
89     // 写入数据
90 
91     rwLock.ReleaseWriteLock();
92 }

View Code

 

PS:本文为博主的原创文章,请尊重博主辛苦码字的成果,转载请注明链接

 

 

本文由葡京网投哪个正规发布于联系我们,转载请注明出处:【葡京网投哪个正规】动手实现读写锁,java并发编程

关键词:

上一篇:用户及角色管理示例,为数据库指定单独用户名

下一篇:没有了