tasks and functions that are not declared as a class method default to a static lifetime, and all variables declared inside will be static as well. So i and j initialize to the value 0 at time 0. Each call to check() increments i and j by 1. If the tasks were declared with an automatic lifetime, then i and j would have an automatic lifetime. That means each time there is a call to check, i and j are allocated, initialized to 0, incremented by 1, and de-allocated upon return of the task.
Class methods can only be declared with an automatic lifetime and the variables inside the method will default to an automatic lifetime. Note that within either method or non-method tasks/functions, you have the option to explicitly declare individual variables with automatic or static lifetimes. You may want to read this post for more details.
Yes, each always block represents a separate thread. And the LRM does not guarantee atomic execution of the ++ operator, so it is possible to clobber a static variable when multiple threads are writing to it simultaneously. However in practice, I don’t think you could ever write a piece of code that shows this behavior.