下面我会对Java与MySQL锁相关知识进行总结,并提供两条示例说明。
Java与MySQL锁相关知识总结
常见的锁类型
1. 行级锁(Record Lock)
行级锁可以在单个数据行上进行加锁和解锁,只锁定某个数据行,可以多个事务在同一时间内操作不同的行数据,避免对其他不相关的事务产生影响。InnoDB存储引擎默认使用行级锁。
2. 表级锁(Table Lock)
表级锁是对整张表加锁,锁定后其他事务不能对该表进行修改的操作。
3. 页级锁(Page Lock)
页级锁是将数据分为若干页,对于某一个页的数据进行加锁,比行级锁粗细度更高,但比表级锁细度更小。
锁的特性
锁具有以下几个特性:
-
排它性:同一时间内,只能有一个事务对同一资源进行修改,其他事务必须等待。
-
持久性:一旦加锁,即使该事务结束,锁也不会自动释放。
3.死锁:如果多个事务同时占用资源并等待其他资源被释放后再继续执行,就会形成死锁。
Java程序中的锁
Java中的锁实现主要有以下几种:
1. synchronized
synchronized是Java中最基本的一种锁机制。可以作用于代码块、方法和类。
示例代码:
public class Sync {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public int getCount() {
synchronized (this) {
return count;
}
}
}
2. ReentrantLock
ReentrantLock是Java SE5的新特征,类似synchronized一样能够实现同步效果,但是比synchronized更加灵活,可以通过tryLock()方法尝试锁定,lockInterruptibly()方法和tryLock(long time,TimeUnit unit)方法具有可中断性。
示例代码:
public class LockDemo {
private int count = 0;
// 创建ReentrantLock实例
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
MySQL中的锁
MySQL中的锁主要有以下两种类型:
1. 共享锁(S锁)
共享锁是读锁,可以被多个线程同时持有,用于保证数据的并发读取。
SELECT * FROM mytable WHERE id=1 LOCK IN SHARE MODE;
2. 排它锁(X锁)
排它锁是写锁,同一时间只能有一个事务占用,用于保证数据的独占性操作。
UPDATE mytable SET field='value' WHERE id=1 LOCK IN SHARE MODE;
示例说明
示例一:Java程序中使用ReentrantLock实现多线程访问共享资源
我们需要实现一个计数器,使用两个线程同时对计数器进行加一操作。
public class Counter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
System.out.println("Thread " + Thread.currentThread().getId() + " increment count to " + count);
} finally {
lock.unlock();
}
}
}
在主函数中,我们启动两个线程对计数器进行累加:
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
运行结果:
Thread 12 increment count to 1
Thread 12 increment count to 2
Thread 12 increment count to 3
Thread 12 increment count to 4
Thread 12 increment count to 5
Thread 11 increment count to 6
Thread 11 increment count to 7
Thread 11 increment count to 8
Thread 11 increment count to 9
Thread 11 increment count to 10
可以看到,通过使用ReentrantLock,两个线程能够同时对计数器进行操作,并且线程安全。
示例二:在MySQL中使用共享锁和排它锁
我们需要实现一个存款和取款的实例,存款和取款都需要对账户进行加锁。
CREATE TABLE account (id INT(10) NOT NULL, money INT(10) NOT NULL DEFAULT '0', PRIMARY KEY (id));
INSERT INTO account(id, money) VALUES(1, 100);
BEGIN;
SELECT * FROM account WHERE id=1 LOCK IN SHARE MODE;
UPDATE account SET money=money+100 WHERE id=1;
COMMIT;
BEGIN;
SELECT * FROM account WHERE id=1 FOR UPDATE;
UPDATE account SET money=money-50 WHERE id=1;
COMMIT;
在事务中,使用SELECT ... LOCK IN SHARE MODE可以对记录加共享锁,使用SELECT ... FOR UPDATE可以对记录加排它锁,保证共享和独占性。
以上就是Java与MySQL锁相关知识的总结及示例说明。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java与Mysql锁相关知识总结 - Python技术站