Java与Mysql锁相关知识总结

  

下面我会对Java与MySQL锁相关知识进行总结,并提供两条示例说明。

Java与MySQL锁相关知识总结

常见的锁类型

1. 行级锁(Record Lock)

行级锁可以在单个数据行上进行加锁和解锁,只锁定某个数据行,可以多个事务在同一时间内操作不同的行数据,避免对其他不相关的事务产生影响。InnoDB存储引擎默认使用行级锁。

2. 表级锁(Table Lock)

表级锁是对整张表加锁,锁定后其他事务不能对该表进行修改的操作。

3. 页级锁(Page Lock)

页级锁是将数据分为若干页,对于某一个页的数据进行加锁,比行级锁粗细度更高,但比表级锁细度更小。

锁的特性

锁具有以下几个特性:

  1. 排它性:同一时间内,只能有一个事务对同一资源进行修改,其他事务必须等待。

  2. 持久性:一旦加锁,即使该事务结束,锁也不会自动释放。

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锁相关知识的总结及示例说明。

相关文章