<section class="mp_profile_iframe_wrp"><mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe js_wx_tap_highlight" data-pluginname="mpprofile" data-weui-theme="light" data-id="Mzg4MzA1MzI4Mw==" data-headimg="http://mmbiz.qpic.cn/sz_mmbiz_png/zJJ31Zu16Uf7vH1N9Gx2MUAsDiaLTBgWZzVHeLAKiaU2ibC9K6JpssVD8YWicHdUYh8XOEicNNxzovu6JUj05WF2h8Q/0?wx_fmt=png" data-nickname="李哥说架构" data-alias="" data-signature="个人提升架,架构知识分享。" data-from="0" data-is_biz_ban="0" data-origin_num="29" data-isban="0" data-biz_account_status="0" data-index="0"></mp-common-profile></section><p>每天分享一个架构知识</p><p><span></span><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; letter-spacing: normal; text-align: start; white-space: pre-wrap; background-color: rgb(247, 247, 248); visibility: visible;">Redission 是一个基于 Redis 的分布式 Java 锁框架,它提供了各种锁实现,包括可重入锁、公平锁、读写锁等。使用 Redission 可以方便地实现分布式锁。</span></p><p><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; letter-spacing: normal; text-align: start; white-space: pre-wrap; background-color: rgb(247, 247, 248); visibility: visible;"><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; letter-spacing: normal; text-align: start; white-space: pre-wrap; visibility: visible;">redisson 实现公平锁 和读写锁的代码</span></span></p><ol class="list-paddingleft-1"><li><p>公平锁:</p></li></ol><pre><div><p><span>java</span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</p><p><code><span>import</span> org.redisson.Redisson;<br><span>import</span> org.redisson.api.RLock;<br><span>import</span> org.redisson.api.RedissonClient;<br><span>import</span> org.redisson.config.Config;<br><br><span>public</span> <span>class</span> <span>FairLockExample</span> {<br> <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(String[] args)</span> {<br> <span>// 创建 Redisson 客户端</span><br> <span>Config</span> <span>config</span> <span>=</span> <span>new</span> <span>Config</span>();<br> config.useSingleServer().setAddress(<span>"redis://127.0.0.1:6379"</span>);<br> <span>RedissonClient</span> <span>redissonClient</span> <span>=</span> Redisson.create(config);<br><br> <span>// 获取公平锁实例</span><br> <span>RLock</span> <span>fairLock</span> <span>=</span> redissonClient.getFairLock(<span>"myFairLock"</span>);<br>
<span>try</span> {
<span>// 加锁</span>
fairLock.lock();
<span>// 在这里执行需要保护的代码块</span>
} <span>finally</span> {
<span>// 释放锁</span>
fairLock.unlock();
}
<span>// 关闭 Redisson 客户端</span>
redissonClient.shutdown();
}
}</code></p></div></pre><p>在上面的示例中,我们使用 <code>redissonClient.getFairLock("myFairLock")</code> 方法获取一个公平锁实例。然后,在 <code>try</code> 块中使用 <code>fairLock.lock()</code> 方法对锁进行加锁操作,然后在需要保护的代码块中执行相应的逻辑。最后,在 <code>finally</code> 块中使用 <code>fairLock.unlock()</code> 方法释放锁。</p><ol start="2" class="list-paddingleft-1"><li><p>读写锁:</p></li></ol><pre><div><p><span>java</span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</p><p><code><span>import</span> org.redisson.Redisson;
<span>import</span> org.redisson.api.RReadWriteLock;
<span>import</span> org.redisson.api.RLock;
<span>import</span> org.redisson.api.RedissonClient;
<span>import</span> org.redisson.config.Config;
<span>public</span> <span>class</span> <span>ReadWriteLockExample</span> {
<span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(String[] args)</span> {
<span>// 创建 Redisson 客户端</span>
<span>Config</span> <span>config</span> <span>=</span> <span>new</span> <span>Config</span>();
config.useSingleServer().setAddress(<span>"redis://127.0.0.1:6379"</span>);
<span>RedissonClient</span> <span>redissonClient</span> <span>=</span> Redisson.create(config);
<span>// 获取读写锁实例</span>
<span>RReadWriteLock</span> <span>readWriteLock</span> <span>=</span> redissonClient.getReadWriteLock(<span>"myReadWriteLock"</span>);
<span>try</span> {
<span>// 获取读锁</span>
<span>RLock</span> <span>readLock</span> <span>=</span> readWriteLock.readLock();
readLock.lock();
<span>// 在这里执行需要保护的读操作</span>
<span>// 获取写锁</span>
<span>RLock</span> <span>writeLock</span> <span>=</span> readWriteLock.writeLock();
writeLock.lock();
<span>// 在这里执行需要保护的写操作</span>
} <span>finally</span> {
<span>// 释放读锁</span>
readLock.unlock();
<span>// 释放写锁</span>
writeLock.unlock();
}
<span>// 关闭 Redisson 客户端</span>
redissonClient.shutdown();
}
}</code></p></div></pre><p>在上面的示例中,我们使用 <code>redissonClient.getReadWriteLock("myReadWriteLock")</code> 方法获取一个读写锁实例。然后,在 <code>try</code> 块中首先获取读锁,并使用 <code>readLock.lock()</code> 方法对读锁进行加锁操作,在需要保护的读操作代码块中执行相应的逻辑。然后,获取写锁,并使用 <code>writeLock.lock()</code> 方法对写锁进行加锁操作,在需要保护的写操作代码块中执行相应的逻辑。最后,在 <code>finally</code> 块中分别使用 <code>readLock.unlock()</code> 和 <code>writeLock.unlock()</code> 方法释放读锁和写锁。</p><p><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-size: 16px;letter-spacing: normal;text-align: start;white-space: pre-wrap;background-color: rgb(247, 247, 248);"><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-size: 16px;letter-spacing: normal;text-align: start;white-space: pre-wrap;">但是他们是如何实现的呢?</span></span></p><ol class="list-paddingleft-1"><li><p>公平锁原理:</p></li><ul class="list-paddingleft-1"><li><p>Redisson 的公平锁实现是基于 Redis 的单线程特性。当多个线程尝试获取公平锁时,它们将按照请求的顺序排队。</p></li><li><p>Redisson 使用 Redis 的命令 <code>SETNX</code> 来实现公平锁。每个请求都会尝试在 Redis 中设置一个键,如果设置成功,则表示获取到了锁;如果设置失败,则表示锁已被其他请求占用。</p></li><li><p>当一个线程成功获取到公平锁后,它将持有该锁直到释放。</p></li></ul><li><p>读写锁原理:</p></li><ul class="list-paddingleft-1"><li><p>Redisson 的读写锁是通过 Redis 的单线程特性和 Redis 的 <code>WATCH</code>、<code>MULTI</code>、<code>EXEC</code> 命令实现的。</p></li><li><p>Redisson 使用一个 Redis 键来表示读写锁,该键存储了读锁和写锁的状态。</p></li><li><p>当一个线程尝试获取读锁时,它会检查写锁是否已被占用,如果没有写锁,则该线程可以获取到读锁;如果有写锁,则需要等待写锁被释放。</p></li><li><p>当一个线程尝试获取写锁时,它会先检查是否有任何线程持有读锁或写锁,如果有,则需要等待锁被释放;如果没有,则可以获取到写锁。</p></li><li><p>Redisson 使用 <code>WATCH</code> 命令来监视读写锁的状态,在获取锁之前,通过 <code>WATCH</code> 命令来监视读写锁的变化,如果读写锁的状态在获取锁期间发生了变化,则事务将自动失败。</p></li></ul></ol><p>总的来说,Redisson 实现公平锁和读写锁的原理都是基于 Redis 提供的原子性操作和分布式锁机制。它使用 Redis 的命令和特性来确保锁的正确获取和释放,并通过 Redisson 的客户端实现封装了这些操作,使得开发者可以更方便地使用公平锁和读写锁来进行并发控制。</p><p><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-size: 16px;letter-spacing: normal;text-align: start;white-space: pre-wrap;background-color: rgb(247, 247, 248);"><spanSegoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-size: 16px;letter-spacing: normal;text-align: start;white-space: pre-wrap;">Redisson 公平锁和读写锁的使用场景</span></span></p><p>公平锁的使用场景:</p><ol class="list-paddingleft-1"><li><p>任务调度:当多个线程或多个节点需要按照请求的顺序依次执行任务时,可以使用公平锁来确保任务按照请求的顺序进行处理,避免出现并发冲突或数据不一致的问题。</p></li><li><p>资源竞争:当多个线程或多个节点需要竞争有限的资源时,可以使用公平锁来实现公平的资源分配,确保每个请求都有机会获取到资源,避免某些请求长时间占用资源而导致其他请求等待过久。</p></li><li><p>排他操作:当某个操作需要在多个线程或多个节点之间进行排他性操作时,可以使用公平锁来确保每次只有一个线程或一个节点能够执行该操作,避免并发冲突和数据不一致的问题。</p></li></ol><p>读写锁的使用场景:</p><ol class="list-paddingleft-1"><li><p>缓存更新:当多个线程或多个节点需要读取缓存数据,并在数据更新时进行写操作时,可以使用读写锁来保证在写操作期间其他线程或节点无法读取数据,避免读取到过期或不一致的数据。</p></li><li><p>数据库访问:当多个线程或多个节点需要对数据库进行读写操作时,可以使用读写锁来实现读写分离,读操作可以并发进行,写操作则需要互斥执行,避免读写冲突和数据不一致的问题。</p></li><li><p>文件操作:当多个线程或多个节点需要对文件进行读写操作时,可以使用读写锁来实现读写分离,多个线程可以并发读取文件内容,写操作则需要互斥执行,确保文件数据的一致性。</p></li></ol><p>这些场景只是公平锁和读写锁的一部分应用示例,实际上,公平锁和读写锁在许多需要并发控制的场景中都可以发挥作用。具体使用哪种锁取决于业务需求和并发访问模式。</p><p>我创建了一个知识星球,专门讨论架构内容,有任何架构方面的问题都可以直接向我提问。</p><p><img class="rich_pages wxw-img js_insertlocalimg js_img_placeholder wx_img_placeholder" data-ratio="1.1074074074074074" data-s="300,640" data-src="https://mmbiz.qpic.cn/sz_mmbiz_jpg/zJJ31Zu16UeBc6vDJpc3y7bNUB91HEglibjLzIlPfBdBHRHYpZyFc0cPRB3DOdJot9tzCFseff5RY19OrvO9Bkw/640?wx_fmt=jpeg" data-type="jpeg" data-w="1080" data-index="1" src="https://upload-images.jianshu.io/upload_images/11186073-466a36de9319fb6b.png" _width="677px" crossorigin="anonymous" alt="图片"></p><p><mp-style-type data-value="3"></mp-style-type></p><blockquote><p>本文使用 <a href="https://www.jianshu.com/p/5709df6fb58d" class="internal">文章同步助手</a> 同步</p></blockquote>