Trong Java, biến volatile và biến static là hai khái niệm quan trọng, nhưng chúng phục vụ các mục đích khác nhau. Biến volatile liên quan đến việc đồng bộ hóa và quản lý đa luồng, trong khi biến static liên quan đến phạm vi và vòng đời của biến trong một lớp. Bài viết này sẽ so sánh hai loại biến này về các khía cạnh khác nhau như định nghĩa, cách sử dụng, và những điểm khác biệt chính.

1. Định nghĩa

Biến volatile

  • Định nghĩa: Biến volatile trong Java là một từ khóa được sử dụng để khai báo rằng một biến có thể được truy cập và thay đổi bởi nhiều luồng (threads) khác nhau. Khi một biến được đánh dấu là volatile, nó đảm bảo rằng giá trị của biến sẽ được đọc từ bộ nhớ chính thay vì từ bộ nhớ cache của từng luồng.
  • Cách sử dụng: Bạn sử dụng từ khóa volatile trong khai báo biến, như sau:
volatile int sharedVariable;

Biến static

  • Định nghĩa: Biến static trong Java là một biến thuộc về lớp thay vì thuộc về bất kỳ thể hiện (instance) nào của lớp. Điều này có nghĩa là tất cả các thể hiện của lớp sẽ chia sẻ cùng một biến static.
  • Cách sử dụng: Bạn sử dụng từ khóa static trong khai báo biến, như sau:
static int staticVariable;

2. Tính chất và cách hoạt động

Tính chất của biến volatile

  • Đồng bộ hóa: Biến volatile cung cấp một cơ chế nhẹ hơn cho việc đồng bộ hóa giữa các luồng. Nó đảm bảo rằng khi một luồng thay đổi giá trị của biến, tất cả các luồng khác sẽ nhìn thấy sự thay đổi ngay lập tức.
  • Không khóa: Việc sử dụng biến volatile không yêu cầu sử dụng khóa (synchronization), giúp giảm độ trễ và tăng hiệu suất trong một số tình huống nhất định.
  • Chỉ số: Biến volatile không đảm bảo an toàn cho nhiều phép toán không nguyên tử (non-atomic operations). Nếu bạn cần thực hiện nhiều phép toán trên biến volatile, bạn vẫn cần sử dụng thêm các cơ chế đồng bộ hóa khác.

Tính chất của biến static

  • Phạm vi và vòng đời: Biến static có phạm vi toàn cục trong lớp và chỉ được khởi tạo một lần khi lớp được tải vào bộ nhớ. Nó tồn tại cho đến khi chương trình kết thúc.
  • Chia sẻ giữa các thể hiện: Tất cả các thể hiện của lớp có thể truy cập cùng một biến static, giúp tiết kiệm bộ nhớ khi bạn cần chia sẻ dữ liệu giữa các thể hiện.
  • Không liên quan đến đồng bộ hóa: Biến static không liên quan đến việc đồng bộ hóa và có thể được truy cập từ nhiều luồng cùng một lúc mà không có cơ chế đồng bộ hóa.

3. Ví dụ minh họa

Ví dụ về biến volatile

class VolatileExample {
    private volatile boolean running = true;

    public void run() {
        while (running) {
            // Thực hiện một số công việc
        }
    }

    public void stop() {
        running = false; // Cập nhật giá trị cho biến volatile
    }
}

Trong ví dụ này, biến running được khai báo là volatile, đảm bảo rằng khi một luồng cập nhật nó, các luồng khác sẽ thấy sự thay đổi ngay lập tức.

Ví dụ về biến static

class StaticExample {
    static int counter = 0;

    public StaticExample() {
        counter++; // Tăng giá trị của biến static
    }

    public static void printCounter() {
        System.out.println("Counter: " + counter);
    }
}

Trong ví dụ này, biến counter là một biến static, được chia sẻ giữa tất cả các thể hiện của lớp StaticExample. Mỗi khi một thể hiện được tạo ra, giá trị của counter sẽ được tăng lên.

4. Điểm khác biệt chính

Tiêu chíBiến volatileBiến static
Tính chấtCung cấp đồng bộ hóa giữa các luồngChia sẻ dữ liệu giữa các thể hiện
Phạm viPhạm vi của biến trong thể hiệnPhạm vi toàn cục trong lớp
Vòng đờiVòng đời như một biến thông thườngTồn tại từ khi lớp được tải đến khi chương trình kết thúc
Đồng bộ hóaĐảm bảo tính đồng bộ nhẹKhông liên quan đến đồng bộ hóa
Sử dụngKhi cần chia sẻ biến giữa các luồngKhi cần biến chung cho tất cả thể hiện

Kết luận

Biến volatile và biến static phục vụ các mục đích khác nhau trong Java. Biến volatile tập trung vào việc đảm bảo đồng bộ hóa giữa các luồng, trong khi biến static giúp chia sẻ dữ liệu giữa các thể hiện trong một lớp. Việc hiểu rõ sự khác biệt và tính chất của hai loại biến này sẽ giúp lập trình viên lựa chọn cách sử dụng phù hợp trong phát triển ứng dụng.